Skip to main content

BlackFrameDetector

Struct BlackFrameDetector 

Source
pub struct BlackFrameDetector { /* private fields */ }
Expand description

Detects black intervals in a video file and returns their start timestamps.

Uses FFmpeg’s blackdetect filter to identify frames or segments where the proportion of “black” pixels exceeds threshold. One Duration is returned per detected black interval (the start of that interval).

§Examples

use ff_analysis::BlackFrameDetector;

let black_starts = BlackFrameDetector::new("video.mp4")
    .threshold(0.1)
    .run()?;

for ts in &black_starts {
    println!("Black interval starts at {:?}", ts);
}

Implementations§

Source§

impl BlackFrameDetector

Source

pub fn new(input: impl AsRef<Path>) -> Self

Creates a new detector for the given video file.

The default threshold is 0.1 (10% of pixels must be below the blackness cutoff for a frame to count as black).

Examples found in repository?
examples/black_frames.rs (line 59)
28fn main() {
29    let mut args = std::env::args().skip(1);
30    let mut input = None::<String>;
31    let mut threshold = 0.1_f64;
32
33    while let Some(flag) = args.next() {
34        match flag.as_str() {
35            "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
36            "--threshold" | "-t" => {
37                let raw = args.next().unwrap_or_default();
38                threshold = raw.parse().unwrap_or_else(|_| {
39                    eprintln!("Invalid threshold: {raw}");
40                    process::exit(1);
41                });
42            }
43            other => {
44                eprintln!("Unknown flag: {other}");
45                process::exit(1);
46            }
47        }
48    }
49
50    let input = input.unwrap_or_else(|| {
51        eprintln!("Usage: black_frames --input <video> [--threshold <0.0–1.0>]");
52        process::exit(1);
53    });
54
55    println!("Detecting black frames in: {input}");
56    println!("Threshold: {threshold:.2}");
57    println!();
58
59    let black_starts = BlackFrameDetector::new(&input)
60        .threshold(threshold)
61        .run()
62        .unwrap_or_else(|e| {
63            eprintln!("Error: {e}");
64            process::exit(1);
65        });
66
67    if black_starts.is_empty() {
68        println!("No black intervals detected.");
69    } else {
70        println!("Detected {} black interval(s):", black_starts.len());
71        for (i, ts) in black_starts.iter().enumerate() {
72            println!("  [{i:3}] {}", fmt_duration(*ts));
73        }
74    }
75}
Source

pub fn threshold(self, t: f64) -> Self

Sets the luminance threshold for black-pixel detection.

Must be in the range [0.0, 1.0]. Higher values make the detector more permissive (more frames qualify as black); lower values are stricter. Passing a value outside this range causes run to return AnalysisError::Failed.

Default: 0.1.

Examples found in repository?
examples/black_frames.rs (line 60)
28fn main() {
29    let mut args = std::env::args().skip(1);
30    let mut input = None::<String>;
31    let mut threshold = 0.1_f64;
32
33    while let Some(flag) = args.next() {
34        match flag.as_str() {
35            "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
36            "--threshold" | "-t" => {
37                let raw = args.next().unwrap_or_default();
38                threshold = raw.parse().unwrap_or_else(|_| {
39                    eprintln!("Invalid threshold: {raw}");
40                    process::exit(1);
41                });
42            }
43            other => {
44                eprintln!("Unknown flag: {other}");
45                process::exit(1);
46            }
47        }
48    }
49
50    let input = input.unwrap_or_else(|| {
51        eprintln!("Usage: black_frames --input <video> [--threshold <0.0–1.0>]");
52        process::exit(1);
53    });
54
55    println!("Detecting black frames in: {input}");
56    println!("Threshold: {threshold:.2}");
57    println!();
58
59    let black_starts = BlackFrameDetector::new(&input)
60        .threshold(threshold)
61        .run()
62        .unwrap_or_else(|e| {
63            eprintln!("Error: {e}");
64            process::exit(1);
65        });
66
67    if black_starts.is_empty() {
68        println!("No black intervals detected.");
69    } else {
70        println!("Detected {} black interval(s):", black_starts.len());
71        for (i, ts) in black_starts.iter().enumerate() {
72            println!("  [{i:3}] {}", fmt_duration(*ts));
73        }
74    }
75}
Source

pub fn run(self) -> Result<Vec<Duration>, AnalysisError>

Runs black-frame detection and returns the start Duration of each detected black interval.

§Errors
  • AnalysisError::Failedthreshold outside [0.0, 1.0], input file not found, or an internal filter-graph error.
Examples found in repository?
examples/black_frames.rs (line 61)
28fn main() {
29    let mut args = std::env::args().skip(1);
30    let mut input = None::<String>;
31    let mut threshold = 0.1_f64;
32
33    while let Some(flag) = args.next() {
34        match flag.as_str() {
35            "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
36            "--threshold" | "-t" => {
37                let raw = args.next().unwrap_or_default();
38                threshold = raw.parse().unwrap_or_else(|_| {
39                    eprintln!("Invalid threshold: {raw}");
40                    process::exit(1);
41                });
42            }
43            other => {
44                eprintln!("Unknown flag: {other}");
45                process::exit(1);
46            }
47        }
48    }
49
50    let input = input.unwrap_or_else(|| {
51        eprintln!("Usage: black_frames --input <video> [--threshold <0.0–1.0>]");
52        process::exit(1);
53    });
54
55    println!("Detecting black frames in: {input}");
56    println!("Threshold: {threshold:.2}");
57    println!();
58
59    let black_starts = BlackFrameDetector::new(&input)
60        .threshold(threshold)
61        .run()
62        .unwrap_or_else(|e| {
63            eprintln!("Error: {e}");
64            process::exit(1);
65        });
66
67    if black_starts.is_empty() {
68        println!("No black intervals detected.");
69    } else {
70        println!("Detected {} black interval(s):", black_starts.len());
71        for (i, ts) in black_starts.iter().enumerate() {
72            println!("  [{i:3}] {}", fmt_duration(*ts));
73        }
74    }
75}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.