avio 0.17.0

Video and audio editing engine: build a Timeline of clips, edit with undo/redo, and render to a file
Documentation

avio

Crates.io Docs.rs License

An editing engine for video and audio: build a Timeline of Clips, edit it with full undo/redo, and render it to a file.

avio is the editing engine at the top of the ff-* crate family. It owns the editing model: an immutable Timeline of Clips across video and audio tracks, the derivation that turns that model into rendered frames, and an Editor with undo/redo. The ff-* primitives it builds on (decode, encode, filter, analysis, remux, stream, preview, GPU render) stay model-free; for standalone primitive work, depend on those crates directly. See the main repository for the full architecture.

What is avio?

avio is a video editing engine: you describe an edit as data and the engine renders it.

  • An editing model, not a wrapper: avio owns an immutable Timeline of Clips across video and audio tracks, which you build, edit, and render.
  • Non-destructive and undoable: every edit is a pure function over the model, and Editor provides full undo/redo where one edit is one step.
  • Renders the model to a file: the engine derives frames from the timeline (compositing, transitions, effects, keyframes) and encodes the result.
  • Built on model-free primitives: the ff-* crates do the decode / encode / filter / render work and impose no editing model; avio is one engine on top of them, and you can build a different one on the same primitives.

Installation

[dependencies]
# The editing engine: Timeline, Clip, Editor, render (build, edit, export).
avio = "0.17"

# With real-time preview:
avio = { version = "0.17", features = ["preview"] }

The editing engine (Timeline / Clip / Editor / render), media probing (open), and analysis are always available — cargo add avio gives you the engine. For standalone primitive work (a raw decoder, encoder, pipeline, stream output, or the GPU compositor), depend on the ff-* crate directly (see Working with the primitives directly).

The ff-* crates and avio share a single workspace version and are released together, so all versions move in lockstep; each is still a separate crate you can depend on on its own.

Feature Flags

The editing engine is always present; the flags add opt-in capabilities.

Feature Enables Default
hwaccel hardware-accelerated export yes
preview real-time TimelinePlayer and Scene types no
serde serde (de)serialization of the model no
gpl GPL-only codecs (x264 / x265) no

Quick Start

Build and render a timeline

Place one clip on a video track, size the canvas, and render the timeline to a file.

use avio::{Clip, EncoderConfig, Timeline};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // One clip on a video track; canvas and frame rate set explicitly.
    let timeline = Timeline::builder()
        .canvas(1920, 1080)
        .frame_rate(30.0)
        .video_track(vec![Clip::new("input.mp4")])
        .build()?;

    // Derive frames from the timeline (composite, encode) in one call.
    timeline.render("output.mp4", EncoderConfig::builder().build())?;

    Ok(())
}

Compose multiple clips and tracks

Tracks composite bottom-up. A clip carries its own timeline offset, source trim, opacity, and an optional transition; overlapping two clips on one track with a crossfade is just an offset plus with_transition.

use std::time::Duration;
use avio::{Clip, Timeline, EncoderConfig, XfadeTransition};

let clip_len = Duration::from_secs(2);
let xfade = Duration::from_millis(500);

let timeline = Timeline::builder()
    .canvas(1920, 1080)
    .frame_rate(30.0)
    // V1: two clips crossfading into each other.
    .video_track(vec![
        Clip::new("a.mp4").trim(Duration::ZERO, clip_len),
        Clip::new("b.mp4")
            .trim(Duration::ZERO, clip_len)
            .offset(clip_len - xfade)
            .with_transition(XfadeTransition::Fade, xfade),
    ])
    // V2: a half-opacity overlay on top.
    .video_track(vec![Clip::new("overlay.mp4").with_opacity(0.5)])
    .build()?;

timeline.render("output.mp4", EncoderConfig::builder().build())?;

Edit with undo/redo

Timeline is immutable and edits are pure: apply(&timeline, &command) returns a new timeline. Editor wraps that with history, where one apply is one undo step. Clips and tracks are addressed by stable ids that survive inserts, removes, and undo/redo.

use avio::{Editor, Command, ClipProperty, EncoderConfig};

let mut editor = Editor::new(timeline);
let clip_id = editor.current().video_tracks()[0].clips[0].id;

editor.apply(&Command::SetClipProperty {
    clip: clip_id,
    property: ClipProperty::Opacity(0.5),
})?;

editor.undo(); // back to full opacity
editor.redo(); // 0.5 again

// `render` consumes a `Timeline`; clone the current version to keep editing.
editor.current().clone().render("output.mp4", EncoderConfig::builder().build())?;

Probe media

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());
}

Working with the primitives directly

avio is the engine; the primitives are the ff-* crates. For standalone decoding, encoding, filtering, analysis, remuxing, streaming, preview, or GPU rendering, depend on the crate you need directly. Each has its own README with worked examples:

Crate For
ff-probe Read-only media metadata
ff-decode Video / audio / image decoding
ff-analysis Scene, silence, BPM, keyframe, scopes
ff-encode Video / audio encoding, per-codec and HDR options
ff-remux Stream-copy trim and audio ops (no re-encode)
ff-filter libavfilter graph construction
ff-pipeline Decode → filter → encode transcode
ff-stream HLS / DASH adaptive streaming
ff-preview Real-time playback, seek, proxy workflow
ff-render GPU compositing (wgpu)

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-analysis Media analysis (scene / silence / BPM / scopes)
ff-encode Video and audio encoding
ff-remux Stream-copy remux (trim, audio ops), no re-encode
ff-filter Filter graph operations
ff-pipeline Decode, filter, encode pipeline
ff-stream HLS / DASH adaptive streaming output
ff-preview Real-time preview and proxy workflow
ff-render GPU compositing pipeline (wgpu)
avio Editing engine (this crate)

MSRV

Rust 1.93.0 (edition 2024).

License

MIT OR Apache-2.0