ff-format 0.3.0

Common types for video/audio processing - the Rust way
Documentation

ff-format

Safe, FFmpeg-agnostic type definitions for video and audio processing.

Overview

ff-format provides shared type definitions used across the ff-* crate family. All APIs are safe — no unsafe code is required. FFmpeg internals are completely hidden behind idiomatic Rust types.

Features

  • Type-safe pixel formats: YUV420p, RGBA, NV12, 10-bit HDR, and more
  • Audio sample formats: F32, I16, planar/packed conversion
  • Precise timestamps: Rational time bases with arithmetic operations
  • Video/Audio frames: Safe abstractions for frame data
  • Stream metadata: Video and audio stream information with builder pattern
  • Media container info: Complete file metadata including multiple streams
  • Color metadata: Color space, range, and primaries for HDR workflows

Minimum Supported Rust Version

Rust 1.93.0 or later (edition 2024).

Module Structure

ff-format/src/
├── lib.rs          # Crate root, prelude
├── pixel.rs        # PixelFormat
├── sample.rs       # SampleFormat
├── time.rs         # Timestamp, Rational
├── frame/          # Frame types
│   ├── mod.rs
│   ├── video.rs    # VideoFrame
│   └── audio.rs    # AudioFrame
├── stream.rs       # VideoStreamInfo, AudioStreamInfo
├── media.rs        # MediaInfo
├── color.rs        # ColorSpace, ColorRange, ColorPrimaries
├── codec.rs        # VideoCodec, AudioCodec
├── channel.rs      # ChannelLayout
└── error.rs        # FormatError, FrameError

Usage

Basic Types

use ff_format::prelude::*;

// Pixel formats
let format = PixelFormat::Yuv420p;
assert!(format.is_planar());
assert_eq!(format.num_planes(), 3);

// Sample formats
let audio_fmt = SampleFormat::F32;
assert!(audio_fmt.is_float());
assert_eq!(audio_fmt.bytes_per_sample(), 4);

// Timestamps with time base
let time_base = Rational::new(1, 90000);
let ts = Timestamp::new(90000, time_base);
assert!((ts.as_secs_f64() - 1.0).abs() < 0.001);

Stream Information

use ff_format::stream::{VideoStreamInfo, AudioStreamInfo};
use ff_format::codec::{VideoCodec, AudioCodec};
use ff_format::{PixelFormat, SampleFormat, Rational};

// Video stream with builder pattern
let video = VideoStreamInfo::builder()
    .index(0)
    .codec(VideoCodec::H264)
    .width(1920)
    .height(1080)
    .frame_rate(Rational::new(30, 1))
    .pixel_format(PixelFormat::Yuv420p)
    .build();

assert_eq!(video.width(), 1920);
assert!(video.is_full_hd());

// Audio stream
let audio = AudioStreamInfo::builder()
    .index(1)
    .codec(AudioCodec::Aac)
    .sample_rate(48000)
    .channels(2)
    .sample_format(SampleFormat::F32)
    .build();

assert!(audio.is_stereo());

Media Container Info

use ff_format::media::MediaInfo;
use std::time::Duration;

let media = MediaInfo::builder()
    .path("/path/to/video.mp4")
    .format("mp4")
    .duration(Duration::from_secs(120))
    .file_size(100_000_000)
    .video_stream(video)
    .audio_stream(audio)
    .metadata("title", "My Video")
    .build();

assert!(media.has_video());
assert!(media.has_audio());
assert_eq!(media.resolution(), Some((1920, 1080)));

License

MIT OR Apache-2.0