ff-probe 0.1.2

Media file metadata extraction - the Rust way
docs.rs failed to build ff-probe-0.1.2
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.
Visit the last successful build: ff-probe-0.6.0

ff-probe

Safe, high-level media file metadata extraction — no unsafe code required.

Overview

ff-probe provides functionality for extracting metadata from media files, including video streams, audio streams, and container information. All APIs are safe — FFmpeg internals are fully encapsulated so you never need to write unsafe code. It serves as the Rust equivalent of ffprobe with a clean, ergonomic API.

Features

  • Container format detection: MP4, MKV, AVI, MOV, WebM, and more
  • Video stream analysis: Codec, resolution, frame rate, pixel format
  • Audio stream analysis: Codec, sample rate, channels, sample format
  • Color metadata: Color space, range, and primaries for HDR workflows
  • Bitrate extraction: Container and stream-level bitrate information
  • Metadata access: Title, artist, album, and custom metadata tags

Minimum Supported Rust Version

Rust 1.93.0 or later (edition 2024).

Module Structure

ff-probe/src/
├── lib.rs      # Crate root, prelude, re-exports
├── info.rs     # open() function, FFmpeg integration
└── error.rs    # ProbeError

Usage

Quick Start

use ff_probe::open;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let info = open("video.mp4")?;

    println!("Format: {}", info.format());
    println!("Duration: {:?}", info.duration());

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

    if let Some(audio) = info.primary_audio() {
        println!("Audio: {} Hz, {} channels",
            audio.sample_rate(),
            audio.channels()
        );
    }

    Ok(())
}

Detailed Information

use ff_probe::{open, ColorSpace, ColorPrimaries};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let info = open("video.mp4")?;

    // Enumerate all video streams
    for (i, stream) in info.video_streams().iter().enumerate() {
        println!("Video stream {}: {} {}x{}",
            i, stream.codec_name(), stream.width(), stream.height());
        println!("  Color space: {:?}", stream.color_space());
        println!("  Color range: {:?}", stream.color_range());

        // Check for HDR content
        if stream.color_primaries() == ColorPrimaries::Bt2020 {
            println!("  HDR content detected!");
        }

        if let Some(bitrate) = stream.bitrate() {
            println!("  Bitrate: {} kbps", bitrate / 1000);
        }
    }

    // Enumerate all audio streams
    for (i, stream) in info.audio_streams().iter().enumerate() {
        println!("Audio stream {}: {} {} Hz, {} ch",
            i, stream.codec_name(), stream.sample_rate(), stream.channels());
        if let Some(lang) = stream.language() {
            println!("  Language: {}", lang);
        }
    }

    // Access container metadata
    if let Some(title) = info.title() {
        println!("Title: {}", title);
    }

    Ok(())
}

Error Handling

use ff_probe::{open, ProbeError};

let result = open("/nonexistent/path.mp4");

match result {
    Err(ProbeError::FileNotFound { path }) => {
        println!("File not found: {}", path.display());
    }
    Err(ProbeError::CannotOpen { path, reason }) => {
        println!("Cannot open {}: {}", path.display(), reason);
    }
    Err(ProbeError::InvalidMedia { path, reason }) => {
        println!("Invalid media {}: {}", path.display(), reason);
    }
    Err(e) => println!("Other error: {}", e),
    Ok(info) => println!("Opened: {}", info.format()),
}

Dependencies

  • ff-format: Common types for video/audio processing
  • ff-sys: FFmpeg FFI bindings

License

MIT OR Apache-2.0