Skip to content

avio

The Rust-native video editing engine, built on safe FFmpeg primitives.

A high-level API over FFmpeg with two layers: an editing engine (tracks, clips, keyframes, GPU compositing, undo/redo) on top of a family of composable, model-free primitive crates you can also use on their own. Application code never needs unsafe.

Crates.io Docs.rs Codecov License

Status: avio is pre-1.0. The API is still evolving and may change between minor versions.

What is avio?

  • Safe by default: every unsafe FFmpeg call is encapsulated, so application code never needs unsafe.
  • Ergonomic: builder APIs, typed formats, and errors that carry human-readable context instead of raw FFmpeg return codes.
  • Two layers: an opinionated editing engine on top of model-free FFmpeg primitives, so you can adopt the whole engine or depend on a single ff-* crate (see Design Philosophy).
  • Focused: a foundation for video delivery services and video editing applications in Rust; it does not try to cover every FFmpeg feature.

Re-encode a video to H.264, reusing the source resolution and frame rate:

use ff_probe::open;
use ff_decode::VideoDecoder;
use ff_encode::{VideoEncoder, VideoCodec, BitrateMode};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Inspect the input and reuse its resolution and frame rate.
    let info = open("input.mp4")?;
    let video = info
        .primary_video()
        .ok_or("input.mp4 has no video stream")?;
    let (width, height, fps) = (video.width(), video.height(), video.fps());
    println!("{width}x{height} @ {fps:.2} fps");

    // A decoder for the input, an encoder for the output.
    let mut decoder = VideoDecoder::open("input.mp4").build()?;
    let mut encoder = VideoEncoder::create("output.mp4")
        .video(width, height, fps)
        .video_codec(VideoCodec::H264)
        .bitrate_mode(BitrateMode::Crf(23)) // 0-51, lower = higher quality
        .build()?;

    // Decode every frame and re-encode it.
    while let Some(frame) = decoder.decode_one()? {
        encoder.push_video(&frame)?;
    }
    encoder.finish()?; // flush buffered frames and finalize the file

    Ok(())
}

Choosing a Rust FFmpeg library

Several good options wrap FFmpeg in Rust. They sit at different levels, so the right one depends on what you are building.

Library Layer Editing model unsafe in your code Runtime dependency Best for
avio + ff-* High-level engine + composable primitives Yes None Linked libav* Video editing apps and delivery services
ffmpeg-next Thin safe wrapper, near 1:1 with libav* No Some Linked libav* Full low-level control of the FFmpeg API
ez-ffmpeg High-level, mirrors the FFmpeg CLI No None Linked libav* Transcoding and filter jobs close to the CLI
video-rs High-level frame toolkit No None Linked libav* Reading and writing frames (CV / ML pipelines)
ffmpeg-sidecar Wraps the ffmpeg binary (subprocess) No None ffmpeg executable Driving the CLI with a clean iterator API

ffmpeg-the-third is an actively maintained fork of ffmpeg-next. For raw FFI bindings, see ffmpeg-sys-next or rusty_ffmpeg. For a non-FFmpeg media framework with its own editing layer, see the gstreamer bindings.

avio is the only one of these that ships an editing model: a timeline of tracks and clips, a per-clip effect stack with keyframes, and a preview that matches the exported result. If you do not need that model, the ff-* primitives underneath it are usable on their own for safe decode, encode, filter, stream, and GPU compositing, with no editing concepts imposed.

Design Philosophy

avio is two layers: an opinionated editing engine on top of model-free FFmpeg primitive crates. Adopt the whole engine, or reach for a single primitive.

avio (the engine)

avio commits to one editing model: tracks, a per-clip effect stack, keyframes, and compositing, with model-to-frame derivation and undo/redo history. If that model fits your app, depend on avio, drive Timeline / Clip, and get a preview that matches the exported result. The engine answers what to edit.

FFmpeg primitive crates

The ff-* crates handle execution (decode, encode, filter, composite one frame, stream) and know nothing about timelines, tracks, or edits. They are model-free by construction (the editing model lives only in avio, at the top of the dependency graph), so nothing forces avio's model on you. Each is usable on its own: build a different editing model (a node-graph compositor, a magnetic timeline), or just do safe Rust media plumbing (decode, encode, transcode, stream). The primitives answer how to execute. See ff-decode for a decode-only example.

Installation

Add the avio engine, or individual ff-* primitives:

[dependencies]
avio = "0.18"

# Or pick individual primitives, without the engine
ff-probe  = "0.18"
ff-decode = "0.18"
ff-encode = "0.18"

All crates share a single workspace version and are released together in lockstep; see Versioning. FFmpeg 7.x or 8.x development libraries must be installed on your system.

Windows

vcpkg install ffmpeg:x64-windows
$env:VCPKG_ROOT = "C:\vcpkg"

macOS

brew install ffmpeg

Linux (Debian/Ubuntu)

sudo apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev

Documentation

API documentation is on docs.rs/avio; each ff-* primitive is documented on its own docs.rs page (linked in Crates).

Crates

Crate Description crates.io docs.rs
avio Editing engine: owns the editing model (Timeline/Clip, derivation, history) and depends on the primitives
ff-probe Media metadata extraction
ff-decode Video and audio decoding
ff-analysis Media analysis (scene, silence, BPM, scopes)
ff-encode Video and audio encoding
ff-remux Stream-copy remux (trim, audio replace/extract/add)
ff-filter Filter graph operations
ff-pipeline Decode, filter, encode pipeline
ff-stream HLS/DASH streaming output
ff-preview Real-time A/V preview and proxy workflow
ff-render GPU compositing pipeline (wgpu)
ff-format Shared type definitions
ff-common Common traits and buffer pooling
ff-sys Low-level FFmpeg FFI bindings

Feature flags

The editing engine (Timeline / Clip / Editor / render), media probing (open), and analysis are always present in avio; the flags add opt-in capabilities on top:

Feature Default Enables
hwaccel yes Hardware-accelerated export (NVENC, QSV, AMF, VideoToolbox, VA-API)
preview Real-time TimelinePlayer and Scene types
serde serde (de)serialization of the editing model
gpl GPL-only codecs (libx264, libx265)

For standalone primitive work (a raw decoder, encoder, pipeline, stream output, or the GPU compositor), depend on the ff-* crate directly; each carries its own feature flags (tokio, srt, render-gpu, and so on).

Versioning

All crates in this repository (avio and the ff-* family) share one workspace version, defined in [workspace.package] in Cargo.toml, and are published together. Their version numbers always move in lockstep; the shared version is bumped only when the crates advance as a set.

Platform support

Platform Status Hardware acceleration
Windows NVENC/NVDEC, QSV, AMF
macOS VideoToolbox
Linux VAAPI, NVENC/NVDEC, QSV

Projects using avio

A terminal media player that renders video as colored ASCII art with synchronized audio. It was migrated from ffmpeg-next / ffmpeg-sys-next to avio, with no direct unsafe FFmpeg code in the application. It uses:

  • VideoDecoder with PixelFormat::Rgb24 for per-pixel luminance mapping
  • AudioDecoder with PCM conversion (SampleFormat::F32) feeding rodio
  • Synchronized audio and video across two threads via crossbeam-channel

A non-linear video editor and the main driver of the library's API. It exercises the full decode, timeline compose, preview, and export path, and is where most bugs and API changes originate. It uses:

  • Timeline / Clip multi-track composition with per-clip colour correction and transitions
  • A real-time preview that matches the exported result
  • The ff-preview proxy workflow, plus scene/silence detection, waveform, and EBU R128 loudness analysis

Contributing

Pull requests, bug reports, and feature requests are welcome. See CONTRIBUTING, and look for issues labeled good first issue or help wanted. avio-editor-demo drives most API changes, so it is a good place to see what is needed next.

Minimum Supported Rust Version

Rust 1.93.0 (edition 2024).

License

Dual-licensed under either MIT or Apache-2.0 at your option.

avio links against FFmpeg, which is LGPL 2.1+ by default. The gpl feature of ff-encode enables GPL-licensed codecs (libx264, libx265); see ff-encode.

Acknowledgements

The audio fixture used in integration tests is provided by Music Atelier Amacha (甘茶の音楽工房), composed by Amacha. Used with permission under the site's free-use terms.

About

A safe, high-level Rust API over FFmpeg for building media applications.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages