use std::path::{Path, PathBuf};
use std::process::Command;
fn have(tool: &str) -> bool {
Command::new(tool)
.arg("-version")
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
fn dir(tag: &str) -> PathBuf {
let d = std::env::temp_dir().join(format!(
"deepshrink-it-compact-{tag}-{}",
std::process::id()
));
let _ = std::fs::remove_dir_all(&d);
std::fs::create_dir_all(&d).expect("create temp dir");
d
}
fn ffmpeg(args: &[&str], out: &Path) {
let status = Command::new("ffmpeg")
.args(["-y", "-hide_banner", "-loglevel", "error"])
.args(args)
.arg(out)
.status()
.expect("spawn ffmpeg");
assert!(status.success(), "ffmpeg fixture failed");
}
fn shrink(input: &Path, extra: &[&str]) -> String {
let out = Command::new(env!("CARGO_BIN_EXE_deepshrink"))
.arg(input)
.args(extra)
.output()
.expect("run deepshrink");
assert!(
out.status.success(),
"deepshrink failed: {}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout).into_owned()
}
#[test]
fn a_compact_video_is_kept_instead_of_growing() {
if !have("ffmpeg") || !have("ffprobe") {
eprintln!("skipping: ffmpeg/ffprobe not found in PATH");
return;
}
let d = dir("video");
let src = d.join("clip.mp4");
ffmpeg(
&[
"-f",
"lavfi",
"-i",
"nullsrc=size=640x360:rate=30:duration=14,geq=random(1)*255:128:128",
"-c:v",
"libx264",
"-preset",
"veryfast",
"-crf",
"38",
],
&src,
);
let before = std::fs::metadata(&src).unwrap().len();
let stdout = shrink(&src, &["--json"]);
let v: serde_json::Value = serde_json::from_str(stdout.trim()).expect("json");
assert_eq!(v["already_compact"], true, "{stdout}");
assert_eq!(
v["final_bytes"].as_u64().unwrap(),
before,
"a byte-for-byte copy"
);
std::fs::remove_file(d.join("clip.shrink.mp4")).unwrap();
let stdout = shrink(&src, &["--json", "--allow-larger"]);
let v: serde_json::Value = serde_json::from_str(stdout.trim()).expect("json");
assert_eq!(v["already_compact"], false);
assert!(v["final_bytes"].as_u64().unwrap() > before, "{stdout}");
let _ = std::fs::remove_dir_all(&d);
}
#[test]
fn a_low_bitrate_mp3_is_kept_not_upsampled() {
if !have("ffmpeg") || !have("ffprobe") {
eprintln!("skipping: ffmpeg/ffprobe not found in PATH");
return;
}
let d = dir("audio");
let src = d.join("book.mp3");
ffmpeg(
&[
"-f",
"lavfi",
"-i",
"sine=frequency=300:duration=20",
"-ac",
"1",
"-b:a",
"48k",
],
&src,
);
let before = std::fs::metadata(&src).unwrap().len();
let stdout = shrink(&src, &["--json"]);
let v: serde_json::Value = serde_json::from_str(stdout.trim()).expect("json");
assert_eq!(v["already_compact"], true, "{stdout}");
assert!(v["output"].as_str().unwrap().ends_with(".mp3"));
assert!(v["final_bytes"].as_u64().unwrap() <= before + 1024);
let stdout = shrink(
&src,
&["--json", "--audio-codec", "opus", "--quality", "fast"],
);
let v: serde_json::Value = serde_json::from_str(stdout.trim()).expect("json");
assert_eq!(v["already_compact"], false);
assert!(v["final_bytes"].as_u64().unwrap() < before, "{stdout}");
let _ = std::fs::remove_dir_all(&d);
}