musicutil/modules/ffprobe/src/lib.rs

68 lines
1.5 KiB
Rust

pub mod errors;
mod ffprobe_output;
pub mod types;
use std::{convert::Into, path::Path, process::Command};
use self::errors::{AnalyzeError, FFProbeError};
fn extract(
path: &Path,
ffprobe_command: Option<&str>,
) -> Result<ffprobe_output::FFProbeOutput, AnalyzeError> {
let output = Command::new(ffprobe_command.unwrap_or("ffprobe"))
.args([
"-v",
"quiet",
"-print_format",
"json",
"-show_format",
"-show_streams",
path.to_str().unwrap(),
])
.output();
if let Err(err) = output {
return Err(AnalyzeError::IOError(err));
}
let output = output.unwrap();
if !output.status.success() {
return Err(AnalyzeError::FFProbeError(FFProbeError {
exit_status: output.status,
stderr: String::from_utf8(output.stderr).unwrap(),
}));
}
let output = String::from_utf8(output.stdout).unwrap();
let ffprobe_out: serde_json::Result<ffprobe_output::FFProbeOutput> =
serde_json::from_str(output.as_str());
Ok(ffprobe_out.unwrap())
}
pub fn analyze(
path: &Path,
ffprobe_command: Option<&str>,
) -> Result<types::FFProbeData, AnalyzeError> {
let raw_data = extract(path, ffprobe_command)?;
let mut data = types::FFProbeData {
tags: raw_data.format.tags.into(),
album_art: None,
};
for stream in raw_data.streams.into_iter() {
if stream.codec_type == "video" {
data.album_art = Some(types::FFProbeAlbumArt {
codec_name: stream.codec_name,
height: stream.height.unwrap(),
width: stream.width.unwrap(),
});
}
}
Ok(data)
}