1use std::{path::Path, process};
18
19use ff_remux::StreamCopyTrimmer;
20
21fn main() {
22 let mut args = std::env::args().skip(1);
23 let mut input = None::<String>;
24 let mut output = None::<String>;
25 let mut start: f64 = 0.0;
26 let mut end: f64 = 10.0;
27
28 while let Some(flag) = args.next() {
29 match flag.as_str() {
30 "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
31 "--output" | "-o" => output = Some(args.next().unwrap_or_default()),
32 "--start" => start = args.next().unwrap_or_default().parse().unwrap_or(0.0),
33 "--end" => end = args.next().unwrap_or_default().parse().unwrap_or(10.0),
34 other => {
35 eprintln!("Unknown flag: {other}");
36 process::exit(1);
37 }
38 }
39 }
40
41 let input = input.unwrap_or_else(|| {
42 eprintln!(
43 "Usage: clip_trim --input <file> --output <file> \
44 --start <seconds> --end <seconds>"
45 );
46 process::exit(1);
47 });
48 let output = output.unwrap_or_else(|| {
49 eprintln!("--output is required");
50 process::exit(1);
51 });
52
53 let in_name = Path::new(&input)
54 .file_name()
55 .and_then(|n| n.to_str())
56 .unwrap_or(&input);
57 let out_name = Path::new(&output)
58 .file_name()
59 .and_then(|n| n.to_str())
60 .unwrap_or(&output);
61
62 println!("Input: {in_name}");
63 println!("Trim: {start:.3}s → {end:.3}s (stream copy — no re-encode)");
64 println!("Output: {out_name}");
65 println!();
66
67 if let Err(e) = StreamCopyTrimmer::new(&input, start, end, &output).run() {
68 eprintln!("Error: {e}");
69 process::exit(1);
70 }
71
72 let size_str = match std::fs::metadata(&output) {
73 Ok(m) => {
74 #[allow(clippy::cast_precision_loss)]
75 let kb = m.len() as f64 / 1024.0;
76 if kb < 1024.0 {
77 format!("{kb:.0} KB")
78 } else {
79 format!("{:.1} MB", kb / 1024.0)
80 }
81 }
82 Err(_) => "(unknown size)".to_string(),
83 };
84
85 println!("Done. {out_name} {size_str}");
86}