Finishes #16 in the three places its earlier remedies missed. `tests/`: the last four local `disc_root()` copies now use `tests/common`, and with them goes the one real hardcoded fallback — `ui_keyframe_record_disc.rs` fell back to an absolute path on one machine, which made `unset SYLPHEED_DISC` a no-op there. Control: with the corpus absent that suite now finishes in 0.00s instead of 57.55s, so it skips rather than finding a disc of its own. `examples/`: seventeen examples defaulted to `/disc`, the mount point inside the CI container. Redundant there — `docker/ci/run` sets `SYLPHEED_DISC=/disc` — and wrong everywhere else, where a missing corpus turned into a file-not-found against a path that has never existed on the host. They now name the variable to set, like the other hundred examples already did. `docker/ci/run`: mount `$SYLPHEED_RES3D` and `$SYLPHEED_ISO` alongside the disc. Only the disc was mounted, so an in-container run sat out the res3d and iso suites while looking like a full one — the defect this issue is about, in the runner itself. Measured in the container on this desktop with all three corpora present: 45 suites / 377 passed / 0 failed / 14 ignored, and `sylpheed-corpus-report.txt` now reports PRESENT for all three rather than for the disc alone. Refs #16. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
61 lines
2.4 KiB
Rust
61 lines
2.4 KiB
Rust
//! Throwaway probe: how long is each region chunk of a movie's voice?
|
|
//!
|
|
//! The question it answers is whether the chunks of a resolved voice region are
|
|
//! CONSECUTIVE SEGMENTS (concatenate them) or ALTERNATE TAKES (chunk 0 is the
|
|
//! whole track). Getting that backwards plays the dialogue three times over.
|
|
use std::process::Command;
|
|
use sylpheed_formats::{media, slb::VoiceLang};
|
|
|
|
fn main() {
|
|
let disc =
|
|
std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC to the extracted disc root");
|
|
let src = media::DirectorySource::new(&disc);
|
|
for movie in ["ADV", "S00A", "RT01A"] {
|
|
let Some((s, e)) = media::resolve_movie_voice_region(&src, movie, VoiceLang::English)
|
|
else {
|
|
println!("{movie}: no region");
|
|
continue;
|
|
};
|
|
let riffs = media::voice_region_riffs(&src, s, e).expect("riffs");
|
|
println!(
|
|
"{movie}: region [{s}, {e}) = {} bytes, {} chunk(s)",
|
|
e - s,
|
|
riffs.len()
|
|
);
|
|
for (i, r) in riffs.iter().enumerate() {
|
|
let p = std::env::temp_dir().join(format!("vc_{movie}_{i}.xma.wav"));
|
|
std::fs::write(&p, r).unwrap();
|
|
// XMA declares no duration, so DECODE it and measure the result.
|
|
let w = std::env::temp_dir().join(format!("vc_{movie}_{i}.wav"));
|
|
let _ = Command::new("ffmpeg")
|
|
.args(["-hide_banner", "-loglevel", "error", "-y", "-i"])
|
|
.arg(&p)
|
|
.arg(&w)
|
|
.output();
|
|
let out = Command::new("ffprobe")
|
|
.args([
|
|
"-v",
|
|
"error",
|
|
"-show_entries",
|
|
"format=duration",
|
|
"-of",
|
|
"csv=p=0",
|
|
])
|
|
.arg(&w)
|
|
.output()
|
|
.unwrap();
|
|
let dur = String::from_utf8_lossy(&out.stdout).trim().to_string();
|
|
if std::env::var("KEEP_WAV").is_ok() {
|
|
let keep = std::path::Path::new(&std::env::var("KEEP_WAV").unwrap())
|
|
.join(format!("{movie}_chunk{i}.wav"));
|
|
let _ = std::fs::rename(&w, &keep);
|
|
println!(" kept -> {}", keep.display());
|
|
} else {
|
|
let _ = std::fs::remove_file(&w);
|
|
}
|
|
println!(" chunk {i}: {} bytes -> {dur} s", r.len());
|
|
let _ = std::fs::remove_file(&p);
|
|
}
|
|
}
|
|
}
|