# avio
[](https://crates.io/crates/avio)
[](https://docs.rs/avio)
[](#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
```toml
[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
| `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
```rust
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
```rust
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:
```rust
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
```rust
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:
```rust
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
```rust
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
```rust
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)
```rust
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)
```rust
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
| `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