//! Are subtitle cue times really seconds? //! //! Every "audio missing" verdict in voice-bank-leading-region.md rests on //! reading `track_voice_cues`' `f32` as seconds. `parse_timing` does compute //! `mm*60 + ss` — but only if the token really is `mm:ss.cc`. The movies are on //! the disc, so their true length is an independent oracle: a cue must land //! INSIDE its own movie. use std::process::Command; use sylpheed_formats::{movie_subtitle, PakArchive}; fn movie_secs(path: &str) -> Option { let out = Command::new("ffprobe") .args([ "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", path, ]) .output() .ok()?; String::from_utf8_lossy(&out.stdout).trim().parse().ok() } fn main() { let disc = std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC"); let lang = PakArchive::open(format!("{disc}/dat/movie/eng.pak")).expect("eng.pak"); let mut checked = 0; let mut over = 0; let mut worst: Vec<(String, f32, f32)> = Vec::new(); let dir = format!("{disc}/dat/movie"); let Ok(rd) = std::fs::read_dir(&dir) else { return }; for e in rd.flatten() { let p = e.path(); if p.extension().is_none_or(|x| x != "wmv") { continue; } let base = p.file_stem().unwrap().to_string_lossy().to_string(); let cues = movie_subtitle::track_voice_cues(&lang, &base); if cues.is_empty() { continue; } let last = cues.iter().map(|(_, t)| *t).fold(0.0f32, f32::max); let Some(secs) = movie_secs(&p.to_string_lossy()) else { continue }; checked += 1; if last > secs { over += 1; worst.push((base, last, secs)); } } worst.sort_by(|a, b| (b.1 - b.2).partial_cmp(&(a.1 - a.2)).unwrap()); println!("movies with cues checked: {checked}"); println!("cues landing AFTER the movie ends: {over}"); for (m, last, secs) in worst.iter().take(8) { println!(" {m:<28} last cue {last:>8.2}s movie {secs:>8.2}s"); } println!( "\nIf cues were centiseconds the last cue would be ~100x too big and \ essentially all {checked} would overflow." ); }