pub mod errors; pub mod types; mod ffprobe_output; use std::{convert::Into, path::Path, process::Command}; use self::errors::{AnalyzeError, FFProbeError}; fn extract(path: &Path, ffprobe_command: Option<&str>) -> Result { 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 = serde_json::from_str(output.as_str()); Ok(ffprobe_out.unwrap()) } pub fn analyze(path: &Path, ffprobe_command: Option<&str>) -> Result { 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) }