ff-filter
Apply video and audio transformations without writing FFmpeg filter-graph strings. Build a chain with method calls; the graph description is generated and validated internally.
ff-filter is a safe, ergonomic wrapper over FFmpeg's libavfilter: build and run video and audio filter graphs without hand-writing filter-graph strings. Errors are typed and contextual (FilterError), so a bad input slot or an FFmpeg build error surfaces as a readable message rather than a raw return code.
It is an independent crate: use it on its own, or combine it with the other ff-* crates to build any media app or editing model. The ff-* crates are model-free primitives that impose no editing model; avio is one editing engine built on top of them.
Installation
[]
= "0.18"
Building a Filter Chain
Filtering needs input frames, so this example decodes them with
ff-decode, runs each through the graph,
and encodes the results with ff-encode
(add both as dependencies to run it):
use VideoDecoder;
use ;
use ;
build() checks the configured steps and returns an Err if a value is out of range or the step set is empty. The underlying FFmpeg graph is constructed lazily on the first push_video / push_audio call, using the first frame's format.
Available Video Operations
A representative selection; see the API docs for the full set (colour grading, blurs, denoise, keying, transitions, text, and more).
| Method | Effect |
|---|---|
trim(start, end) |
Discard frames outside the given time range (secs) |
scale(w, h, algorithm) |
Resize frames using the given resampling algorithm |
fit_to_aspect(w, h, color) |
Scale to fit w × h, preserving aspect (letterbox) |
crop(x, y, w, h) |
Extract a rectangular region |
overlay(x, y) |
Composite a second video stream at (x, y) |
fade_in(start, duration) |
Fade from black, starting at start (secs) |
fade_out(start, duration) |
Fade to black, starting at start (secs) |
rotate(degrees, fill_color) |
Rotate clockwise; exposed corners filled with color |
tone_map(ToneMap::Hable) |
HDR-to-SDR tone mapping with the selected curve |
Available Audio Operations
| Method | Effect |
|---|---|
volume(gain_db) |
Adjust loudness by the given number of dB |
equalizer(bands) |
Apply a multi-band parametric EQ (Vec<EqBand>) |
amix(inputs) |
Mix multiple audio streams into one |
Hardware Acceleration
use ;
let graph = builder
.scale
.hardware
.build?;
HwAccel selects the device type (Cuda, VideoToolbox, or Vaapi). When
hardware is enabled, hwupload / hwdownload filters are inserted around the
chain automatically.
Using the Filter Graph
The single-input loop is shown in Building a Filter Chain
above: push each decoded frame into slot 0 with push_video, then drain the
graph with pull_video.
Multi-input filters (such as xfade or overlay) read from additional slots:
push clip A frames to slot 0 and clip B frames to slot 1.
// `graph` built with .overlay(x, y); `frame_a` / `frame_b` are VideoFrames
// from two decoders.
graph.push_video?; // main stream → slot 0
graph.push_video?; // overlay stream → slot 1
while let Some = graph.pull_video?
Error Handling
| Variant | When it occurs |
|---|---|
FilterError::InvalidConfig |
A configured value is out of range (returned by build()) |
FilterError::BuildFailed |
No steps were added, or the FFmpeg graph cannot be built |
FilterError::InvalidInput |
A frame was pushed to an out-of-range input slot |
FilterError::ProcessFailed |
A push or pull operation failed |
FilterError::Ffmpeg |
An underlying FFmpeg function returned an error code |
FilterError::CompositionFailed |
A multi-track composition or mixing operation failed |
FilterError::AnalysisFailed |
An analysis operation (e.g. loudness measurement) failed |
FilterError::GplRequired |
A filter needing the gpl feature was used without it |
MSRV
Rust 1.93.0 (edition 2024).
License
MIT OR Apache-2.0