annie.media.decode

Frame-reading wrapper over torchcodec (infrastructure).

torchcodec and the rest of the PyTorch ecosystem are an optional dependency (the media extra). Everything here imports them lazily, so importing annie — and running the bulk of the test suite — never requires a 2 GB torch install. Call media_available() to check, and the loaders raise a clear MediaUnavailableError if torchcodec is missing.

Two seek modes are exposed (per the design):

  • approximate — fast preview scrubbing (Browse thumbnails / strips).

  • exact — frame-accurate reads for the Annotator (guarantees frame i is frame i).

Frames are returned as numpy uint8 arrays in HWC/RGB order, which is what the Pillow-based overlay renderer in annie.color consumes.

Attributes

SeekMode

"exact" for frame accuracy, "approximate" for speed.

DecoderBackend

torchcodec's VideoDecoder).

Exceptions

MediaUnavailableError

Raised when a frame-decode operation needs torchcodec but it is absent.

Classes

VideoMetadata

Basic video metadata needed by the render/preview pipeline.

Functions

media_available(→ bool)

Return whether the optional torchcodec backend can be imported.

use_decoder_backend(→ collections.abc.Generator[None])

Decode with another backend while the block runs (e.g. a fake decoder in tests).

check_decoder(→ MediaUnavailableError | None)

Load the decoder once and remember why it failed (run off the event loop).

decoder_problem_found(→ str | None)

The problem check_decoder() found, without loading anything.

read_frame(→ numpy.ndarray)

Read a single frame by index.

read_frames(→ list[numpy.ndarray])

Read several frames by index.

frame_count(→ int)

Return the number of frames in a video.

video_metadata(→ VideoMetadata)

Read frame count, dimensions, and fps for a video.

read_strip(→ tuple[list[int], list[numpy.ndarray], int])

Read evenly spaced sample frames for the Browse strip in one pass.

strip_indices(→ list[int])

Compute evenly spaced sample indices for the Browse 5-frame strip.

Module Contents

annie.media.decode.SeekMode

"exact" for frame accuracy, "approximate" for speed.

Type:

Frame-seek strategy

exception annie.media.decode.MediaUnavailableError[source]

Bases: RuntimeError

Raised when a frame-decode operation needs torchcodec but it is absent.

Initialize self. See help(type(self)) for accurate signature.

annie.media.decode.media_available() → bool[source]

Return whether the optional torchcodec backend can be imported.

A None entry in sys.modules is Python’s own “this import is blocked” marker; it counts as not installed.

Returns:

True if torchcodec is importable, False otherwise.

annie.media.decode.DecoderBackend

torchcodec’s VideoDecoder).

Type:

Loads the video-decoder class (default

annie.media.decode.use_decoder_backend(load: DecoderBackend) → collections.abc.Generator[None][source]

Decode with another backend while the block runs (e.g. a fake decoder in tests).

The backend replaces torchcodec entirely, including the “is the extra installed” check; whatever it raises is handled exactly like a torchcodec load failure.

Parameters:

load – Returns the decoder class, or raises ImportError/OSError when the backend cannot load.

annie.media.decode.check_decoder() → MediaUnavailableError | None[source]

Load the decoder once and remember why it failed (run off the event loop).

Returns:

The error, whose message says what to do, or None when frames can be decoded or the media extra is not installed (which is reported separately).

annie.media.decode.decoder_problem_found() → str | None[source]

The problem check_decoder() found, without loading anything.

annie.media.decode.read_frame(path: str | pathlib.Path, frame_idx: int, *, seek_mode: SeekMode = 'exact') → numpy.ndarray[source]

Read a single frame by index.

Parameters:
  • path – Path to the video file.

  • frame_idx – Zero-based frame index to read.

  • seek_mode – "exact" (frame-accurate) or "approximate" (fast).

Returns:

The frame as an HWC uint8 RGB numpy array.

Raises:

MediaUnavailableError – If torchcodec is not installed.

annie.media.decode.read_frames(path: str | pathlib.Path, indices: list[int], *, seek_mode: SeekMode = 'approximate') → list[numpy.ndarray][source]

Read several frames by index.

Parameters:
  • path – Path to the video file.

  • indices – Zero-based frame indices to read.

  • seek_mode – Seek mode; defaults to "approximate" for fast previews.

Returns:

One HWC uint8 RGB numpy array per requested index, in order.

Raises:

MediaUnavailableError – If torchcodec is not installed.

annie.media.decode.frame_count(path: str | pathlib.Path) → int[source]

Return the number of frames in a video.

Parameters:

path – Path to the video file.

Returns:

The total frame count.

Raises:

MediaUnavailableError – If torchcodec is not installed.

class annie.media.decode.VideoMetadata[source]

Basic video metadata needed by the render/preview pipeline.

num_frames

Total decoded frame count.

width

Frame width in pixels.

height

Frame height in pixels.

fps

Average frames per second.

annie.media.decode.video_metadata(path: str | pathlib.Path) → VideoMetadata[source]

Read frame count, dimensions, and fps for a video.

Parameters:

path – Path to the video file.

Returns:

The VideoMetadata.

Raises:

MediaUnavailableError – If torchcodec is not installed.

annie.media.decode.read_strip(path: str | pathlib.Path, count: int = 5, *, seek_mode: SeekMode = 'exact') → tuple[list[int], list[numpy.ndarray], int][source]

Read evenly spaced sample frames for the Browse strip in one pass.

Defaults to "exact" seek mode: in "approximate" mode torchcodec derives num_frames from duration × fps, which can over-report the true count for some clips and make the last sample index point past the real end (raising “no more frames left to decode”). Exact mode scans the file so the count and every sampled index are valid; decoding is still guarded per frame.

Parameters:
  • path – Path to the video file.

  • count – Number of evenly spaced frames (first / ¼ / ½ / ¾ / last by default).

  • seek_mode – Seek mode; "exact" for an accurate frame count.

Returns:

the sampled frame indices that decoded, their HWC uint8 RGB arrays (aligned), and the total frame count.

Return type:

An (indices, frames, num_frames) triple

Raises:

MediaUnavailableError – If torchcodec is not installed.

annie.media.decode.strip_indices(total: int, count: int = 5) → list[int][source]

Compute evenly spaced sample indices for the Browse 5-frame strip.

Returns indices at first / ¼ / ½ / ¾ / last by default. Pure arithmetic, so it needs no media backend and is unit-tested directly.

Parameters:
  • total – Total number of frames in the video (must be >= 1).

  • count – How many sample indices to return (>= 1).

Returns:

A sorted list of count distinct-where-possible frame indices.

Raises:

ValueError – If total < 1 or count < 1.