Files
Sylpheed/crates/sylpheed-export/examples/voice_chunks.rs
sim cc9392bde4 test: one disc resolver, no machine-specific defaults, all three corpora in the container
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>
2026-09-17 22:18:59 +02:00

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);
}
}
}