avio 0.7.0

Safe, high-level audio/video/image processing for Rust — backend-agnostic multimedia toolkit
docs.rs failed to build avio-0.7.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

avio

Crates.io Docs.rs License

avio is the unified facade for the ff-* crate family. Depend on a single crate and opt in to only the capabilities you need via feature flags.

Installation

[dependencies]

# Default: probe + decode + encode

avio = "0.7"



# Add filtering

avio = { version = "0.7", features = ["filter"] }



# Full stack (implies filter + pipeline)

avio = { version = "0.7", features = ["stream"] }



# Async decode/encode (requires tokio runtime)

avio = { version = "0.7", features = ["tokio"] }

Feature Flags

Feature Enables Default
probe ff-probe — read-only media metadata yes
decode ff-decode — video and audio decoding yes
encode ff-encode — video and audio encoding yes
filter ff-filter — filter graph operations no
pipeline ff-pipeline — decode → filter → encode no
stream ff-stream — HLS / DASH streaming output no
tokio Async wrappers for decode and encode no

Quick Start

Probe

use avio::open;

let info = open("video.mp4")?;
if let Some(video) = info.primary_video() {
    println!("{}x{} @ {:.2} fps ({:?})", video.width(), video.height(), video.fps(), video.codec());
}

Decode

use avio::{VideoDecoder, AudioDecoder, PixelFormat, SampleFormat};

// Video — request RGB24 output (FFmpeg converts internally)
let mut vdec = VideoDecoder::open("video.mp4")
    .output_format(PixelFormat::Rgb24)
    .build()?;
while let Some(frame) = vdec.decode_one()? {
    // frame.data() contains raw pixel bytes
}

// Audio — resample to f32 at 44.1 kHz
let mut adec = AudioDecoder::open("audio.flac")
    .output_format(SampleFormat::F32)
    .output_sample_rate(44_100)
    .build()?;
while let Some(frame) = adec.decode_one()? {
    // frame.to_f32_interleaved() returns interleaved f32 samples
}

Image Sequences

A %-pattern path (e.g. frame%04d.png) automatically selects the image2 demuxer for decode and muxer for encode:

use avio::{VideoDecoder, VideoEncoder, VideoCodec, HardwareAccel};

// Decode numbered PNGs → video
let mut decoder = VideoDecoder::open("frames/frame%04d.png")
    .hardware_accel(HardwareAccel::None)
    .frame_rate(25)
    .build()?;

// Encode video → numbered PNGs
let mut encoder = VideoEncoder::create("out/frame%04d.png")
    .video(1920, 1080, 25.0)
    .video_codec(VideoCodec::Png)
    .build()?;

Encode

use avio::{VideoEncoder, VideoCodec, AudioCodec, BitrateMode};

let mut encoder = VideoEncoder::create("output.mp4")
    .video(1920, 1080, 30.0)
    .video_codec(VideoCodec::H264)
    .bitrate_mode(BitrateMode::Crf(23))
    .audio(48_000, 2)
    .audio_codec(AudioCodec::Aac)
    .build()?;

for frame in &video_frames {
    encoder.push_video(frame)?;
}
encoder.finish()?;

Per-Codec Options

VideoCodecOptions and AudioCodecOptions provide typed, per-codec configuration applied before the codec is opened:

use avio::{
    VideoEncoder, VideoCodec, VideoCodecOptions,
    H264Options, H264Profile, H264Preset,
    BitrateMode,
};

let opts = VideoCodecOptions::H264(H264Options {
    profile: H264Profile::High,
    level: Some(41),
    bframes: 2,
    gop_size: 250,
    refs: 3,
    preset: Some(H264Preset::Fast),
    tune: None,
});

let mut encoder = VideoEncoder::create("output.mp4")
    .video(1920, 1080, 30.0)
    .video_codec(VideoCodec::H264)
    .bitrate_mode(BitrateMode::Crf(23))
    .codec_options(opts)
    .build()?;

Available option structs: H264Options, H265Options, Av1Options, SvtAv1Options, Vp9Options, ProResOptions, DnxhdOptions, OpusOptions, AacOptions, Mp3Options, FlacOptions.

Professional Formats

use avio::{
    VideoEncoder, VideoCodec, VideoCodecOptions,
    ProResOptions, ProResProfile, PixelFormat,
};

let mut encoder = VideoEncoder::create("output.mov")
    .video(1920, 1080, 25.0)
    .video_codec(VideoCodec::ProRes)
    .pixel_format(PixelFormat::Yuv422p10le)
    .codec_options(VideoCodecOptions::ProRes(ProResOptions {
        profile: ProResProfile::Hq,
        vendor: None,
    }))
    .build()?;

HDR Metadata

use avio::{
    VideoEncoder, VideoCodec, VideoCodecOptions,
    H265Options, H265Profile, PixelFormat, BitrateMode,
    Hdr10Metadata, MasteringDisplay, ColorTransfer,
};

// HDR10 — PQ transfer + MaxCLL/MaxFALL side data
let mut encoder = VideoEncoder::create("output.mkv")
    .video(3840, 2160, 24.0)
    .video_codec(VideoCodec::H265)
    .bitrate_mode(BitrateMode::Crf(22))
    .pixel_format(PixelFormat::Yuv420p10le)
    .codec_options(VideoCodecOptions::H265(H265Options {
        profile: H265Profile::Main10,
        ..H265Options::default()
    }))
    .hdr10_metadata(Hdr10Metadata {
        max_cll: 1000, max_fall: 400,
        mastering_display: MasteringDisplay {
            red_x: 17000, red_y: 8500,
            green_x: 13250, green_y: 34500,
            blue_x: 7500, blue_y: 3000,
            white_x: 15635, white_y: 16450,
            min_luminance: 50,
            max_luminance: 10_000_000,
        },
    })
    .build()?;

// HLG — broadcast HDR without MaxCLL/MaxFALL
use avio::{ColorSpace, ColorPrimaries};
let mut encoder = VideoEncoder::create("output.mkv")
    .video(1920, 1080, 50.0)
    .video_codec(VideoCodec::H265)
    .pixel_format(PixelFormat::Yuv420p10le)
    .color_transfer(ColorTransfer::Hlg)
    .color_space(ColorSpace::Bt2020)
    .color_primaries(ColorPrimaries::Bt2020)
    .build()?;

Async (tokio feature)

use avio::{AsyncVideoDecoder, AsyncVideoEncoder, VideoEncoder, VideoCodec};
use futures::StreamExt;

let mut encoder = AsyncVideoEncoder::from_builder(
    VideoEncoder::create("output.mp4")
        .video(1920, 1080, 30.0)
        .video_codec(VideoCodec::H264),
)?;

let stream = AsyncVideoDecoder::open("input.mp4").await?.into_stream();
tokio::pin!(stream);
while let Some(Ok(frame)) = stream.next().await {
    encoder.push(frame).await?;
}
encoder.finish().await?;

Pipeline (pipeline feature)

use avio::{Pipeline, EncoderConfig, VideoCodec, AudioCodec, BitrateMode};

Pipeline::builder()
    .input("input.mp4")
    .output("output.mp4", EncoderConfig::builder()
        .video_codec(VideoCodec::H264)
        .audio_codec(AudioCodec::Aac)
        .bitrate_mode(BitrateMode::Crf(23))
        .build())
    .build()?
    .run()?;

Crate Family

Crate Purpose
ff-sys Raw bindgen FFI — internal use only
ff-common Shared buffer-pooling abstractions
ff-format Pure-Rust type definitions (no FFmpeg linkage)
ff-probe Read-only media metadata extraction
ff-decode Video and audio decoding
ff-encode Video and audio encoding
ff-filter Filter graph operations
ff-pipeline Decode → filter → encode pipeline
ff-stream HLS / DASH adaptive streaming output
avio Unified facade (this crate)

MSRV

Rust 1.93.0 (edition 2024).

License

MIT OR Apache-2.0