ff-decode
Decode video and audio frames without managing codec contexts, packet queues, or timestamp conversions. Open a file, call decode_one in a loop, and receive VideoFrame objects with their position already expressed as a Timestamp.
Installation
[]
= "0.7"
= "0.7"
Video Decoding
use VideoDecoder;
use PixelFormat;
let mut decoder = open
.output_format
.build?;
while let Some = decoder.decode_one?
Iterator API
VideoDecoder and AudioDecoder implement Iterator and FusedIterator:
for frame in decoder
Audio Decoding
use AudioDecoder;
use SampleFormat;
let mut decoder = open
.output_format
.output_sample_rate
.output_channels // downmix to stereo
.build?;
while let Some = decoder.decode_one?
Image Sequence Decoding
When a path contains % (printf-style pattern), VideoDecoder automatically
uses the image2 demuxer. Supported extensions: .png, .jpg, .bmp, .tiff.
use ;
// Decode a numbered PNG sequence at 25 fps.
let mut decoder = open
.hardware_accel // recommended for still images
.frame_rate
.build?;
while let Some = decoder.decode_one?
OpenEXR Sequence Decoding
OpenEXR sequences use the same %-pattern mechanism. EXR frames decode as
gbrpf32le (32-bit float, three planes ordered G/B/R):
use ;
use PixelFormat;
// Hardware decoders do not support EXR; always use HardwareAccel::None.
let mut decoder = open
.hardware_accel
.frame_rate
.build?; // returns DecodeError::DecoderUnavailable if --enable-decoder=exr
// was omitted from the FFmpeg build
while let Some = decoder.decode_one?
10-bit and High-Bit-Depth Formats
HDR and professional content often uses 10-bit pixel formats. Request conversion
via .output_format() or leave unset to receive frames in the native format:
use PixelFormat;
// Receive frames in the native 10-bit format (no conversion).
let mut decoder = open.build?;
// Or convert to a specific format for processing.
let mut decoder = open
.output_format
.build?;
Common 10-bit formats: Yuv420p10le, Yuv422p10le, Yuv444p10le, P010Le.
Scaled Output
use VideoDecoder;
use PixelFormat;
let mut decoder = open
.output_format
.output_size // scale + pixel-format conversion in one pass
.build?;
Seeking
use ;
use Duration;
let mut decoder = open.build?;
// Jump to the nearest keyframe at or before 30 seconds.
decoder.seek?;
// Jump to the exact position (may decode additional frames internally).
decoder.seek?;
Seeking does not re-open the file. The existing codec context is flushed and reused.
Hardware Acceleration
use ;
let mut decoder = open
.hardware_accel
.build?;
HardwareAccel::Auto probes for NVDEC, DXVA2, VideoToolbox, and VAAPI in that order, and falls back to software decoding if none is available.
Error Handling
| Variant | When it occurs |
|---|---|
DecodeError::FileNotFound |
The input path does not exist |
DecodeError::CannotOpen |
FFmpeg could not open the container or codec |
DecodeError::UnsupportedCodec |
No decoder available for the stream's codec |
DecodeError::DecoderUnavailable |
Codec is known but not compiled into FFmpeg |
DecodeError::InvalidConfig |
Builder options are inconsistent or unsupported |
DecodeError::Io |
Read error on the underlying file |
What the Crate Handles for You
- Codec context allocation and lifetime
- PTS-to-
Timestampconversion using the stream's time base - Packet queue management and buffering
- EOF signalled as
Ok(None)rather than a special error variant - Pixel format and sample format negotiation via
swscale/swresample image2demuxer selection for%-pattern paths (image sequences)
Feature Flags
| Flag | Description | Default |
|---|---|---|
tokio |
Enables AsyncVideoDecoder and AsyncAudioDecoder. Wraps each blocking FFmpeg call in tokio::task::spawn_blocking and exposes a futures::Stream interface via into_stream(). Requires a tokio 1.x runtime. |
disabled |
[]
= { = "0.7", = ["tokio"] }
When the tokio feature is disabled, only the synchronous VideoDecoder and AudioDecoder APIs are compiled. No tokio dependency is pulled in.
MSRV
Rust 1.93.0 (edition 2024).
License
MIT OR Apache-2.0