use std::process;
use std::time::Duration;
use avio::{AudioDecoder, VideoDecoder};
fn fmt_duration(d: Duration) -> String {
let s = d.as_secs();
let h = s / 3600;
let m = (s % 3600) / 60;
let sec = s % 60;
let ms = d.subsec_millis();
format!("{h:02}:{m:02}:{sec:02}.{ms:03}")
}
fn fmt_bitrate(bps: u64) -> String {
if bps >= 1_000_000 {
let whole = bps / 1_000_000;
let frac = (bps % 1_000_000) / 100_000;
format!("{whole}.{frac} Mbps")
} else {
format!("{} kbps", bps / 1_000)
}
}
fn main() {
let mut args = std::env::args().skip(1);
let mut input = None::<String>;
while let Some(flag) = args.next() {
match flag.as_str() {
"--input" | "-i" => input = Some(args.next().unwrap_or_default()),
other => {
eprintln!("Unknown flag: {other}");
process::exit(1);
}
}
}
let input = input.unwrap_or_else(|| {
eprintln!("Usage: decode_metadata --input <file>");
process::exit(1);
});
let video_result = VideoDecoder::open(&input).build();
if let Ok(dec) = video_result {
let ci = dec.container_info();
let si = dec.stream_info();
println!("Container");
println!(" format: {}", ci.format_name());
match ci.bit_rate() {
Some(br) => println!(" bit_rate: {}", fmt_bitrate(br)),
None => println!(" bit_rate: (unknown)"),
}
println!(" nb_streams: {}", ci.nb_streams());
println!();
println!("Video stream");
println!(
" codec: {} {}×{} {:?} {:.3} fps",
si.codec_name(),
si.width(),
si.height(),
si.pixel_format(),
si.fps(),
);
match dec.duration_opt() {
Some(d) => println!(" duration: {}", fmt_duration(d)),
None => println!(" duration: (unknown — live stream or raw format)"),
}
return;
}
let audio_result = AudioDecoder::open(&input).build();
match audio_result {
Ok(dec) => {
let ci = dec.container_info();
let si = dec.stream_info();
println!("Container");
println!(" format: {}", ci.format_name());
match ci.bit_rate() {
Some(br) => println!(" bit_rate: {}", fmt_bitrate(br)),
None => println!(" bit_rate: (unknown)"),
}
println!(" nb_streams: {}", ci.nb_streams());
println!();
println!("Audio stream");
println!(
" codec: {} {} Hz {}ch {:?}",
si.codec_name(),
si.sample_rate(),
si.channels(),
si.sample_format(),
);
match dec.duration_opt() {
Some(d) => println!(" duration: {}", fmt_duration(d)),
None => println!(" duration: (unknown — live stream or raw format)"),
}
}
Err(e) => {
eprintln!("Error: could not open '{input}' as video or audio: {e}");
process::exit(1);
}
}
}