Skip to main content

scene_detection/
scene_detection.rs

1//! Detect scene changes in a video file and print their timestamps.
2//!
3//! Uses [`SceneDetector`] to identify hard cuts and transitions. The detection
4//! threshold controls sensitivity: lower values report more cuts (including
5//! subtle ones); higher values report only hard cuts.
6//!
7//! # Usage
8//!
9//! ```bash
10//! cargo run --example scene_detection -- --input video.mp4
11//! cargo run --example scene_detection -- --input video.mp4 --threshold 0.3
12//! ```
13
14use std::process;
15
16use ff_analysis::SceneDetector;
17
18fn main() {
19    let mut args = std::env::args().skip(1);
20    let mut input = None::<String>;
21    let mut threshold = 0.4_f64;
22
23    while let Some(flag) = args.next() {
24        match flag.as_str() {
25            "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
26            "--threshold" | "-t" => {
27                let raw = args.next().unwrap_or_default();
28                threshold = raw.parse().unwrap_or_else(|_| {
29                    eprintln!("Invalid threshold: {raw}");
30                    process::exit(1);
31                });
32            }
33            other => {
34                eprintln!("Unknown flag: {other}");
35                process::exit(1);
36            }
37        }
38    }
39
40    let input = input.unwrap_or_else(|| {
41        eprintln!("Usage: scene_detection --input <video> [--threshold <0.0–1.0>]");
42        process::exit(1);
43    });
44
45    println!("Detecting scene changes in: {input}");
46    println!("Threshold: {threshold:.2}");
47    println!();
48
49    let cuts = SceneDetector::new(&input)
50        .threshold(threshold)
51        .run()
52        .unwrap_or_else(|e| {
53            eprintln!("Error: {e}");
54            process::exit(1);
55        });
56
57    if cuts.is_empty() {
58        println!("No scene changes detected.");
59    } else {
60        println!("Detected {} scene change(s):", cuts.len());
61        for (i, ts) in cuts.iter().enumerate() {
62            let secs = ts.as_secs_f64();
63            let h = ts.as_secs() / 3600;
64            let m = (ts.as_secs() % 3600) / 60;
65            let s = ts.as_secs() % 60;
66            let ms = ts.subsec_millis();
67            println!("  [{i:3}] {h:02}:{m:02}:{s:02}.{ms:03}  ({secs:.3}s)");
68        }
69    }
70}