Skip to main content

av_drift_detector/
lib.rs

1//! Generate machine-readable A/V sync test videos and measure audio/video drift.
2//!
3//! Every video frame of a generated file carries its frame number three ways:
4//! a 48-bit barcode strip (with a CRC), a QR code, and a seven-segment
5//! timecode for people. Every frame's worth of audio carries the same number
6//! (mod 65536) as four simultaneous tones. Analysis decodes both sides of a
7//! captured or re-encoded copy and reports, frame by frame, how far the audio
8//! has drifted from the video. Precision is a small fraction of a millisecond.
9//!
10//! ```no_run
11//! use av_drift_detector::{AnalyzeOptions, GenerateOptions, analyze, generate};
12//!
13//! let fps = "29.97".parse()?;
14//! generate(&GenerateOptions::new("sync.mp4", fps, 10.0), |_| {})?;
15//! // ... play `sync.mp4` through the system under test and record it ...
16//! let report = analyze("captured.mp4".as_ref(), &AnalyzeOptions::default())?;
17//! println!("{}", report.summary_text());
18//! # Ok::<(), av_drift_detector::Error>(())
19//! ```
20//!
21//! The pattern rendering ([`pattern`]), audio code ([`audio`]) and the analysis
22//! itself ([`analyze::analyze_scan`]) are plain Rust. Only file input and output
23//! need FFmpeg: linked, with the `ffmpeg` feature (on by default), or run as the
24//! `ffmpeg` and `ffprobe` programs, with the `ffmpeg-cli` feature. Without
25//! either, the crate builds for targets such as Android and WebAssembly.
26
27pub mod analyze;
28pub mod audio;
29mod error;
30pub mod media;
31pub mod pattern;
32pub mod report;
33pub mod timing;
34
35pub use analyze::AnalyzeOptions;
36#[cfg(feature = "ffmpeg")]
37pub use analyze::analyze;
38pub use error::{Error, Result};
39#[cfg(feature = "ffmpeg")]
40pub use media::encode::generate;
41pub use media::{AudioCodec, GenerateOptions, Progress, VideoCodec};
42pub use report::{CaptureMode, DriftReport, DriftSummary, FrameDrift, FrameStatus};
43pub use timing::{FrameRate, parse_time};
44
45// Compile the examples in the README and the library guide as doctests.
46#[cfg(all(doctest, feature = "ffmpeg"))]
47#[doc = include_str!("../../../README.md")]
48struct ReadmeDoctests;
49
50#[cfg(all(doctest, feature = "ffmpeg"))]
51#[doc = include_str!("../../../docs/library.md")]
52struct LibraryGuideDoctests;