diff --git a/modules/ffprobe/src/errors.rs b/modules/ffprobe/src/errors.rs index f1ee6c3..bd2c47a 100644 --- a/modules/ffprobe/src/errors.rs +++ b/modules/ffprobe/src/errors.rs @@ -5,6 +5,7 @@ pub enum AnalyzeError { FFProbeError(FFProbeError), IOError(io::Error), ParseError(serde_json::Error), + TagsMissing(), } impl std::error::Error for AnalyzeError {} @@ -15,6 +16,7 @@ impl fmt::Display for AnalyzeError { AnalyzeError::FFProbeError(err) => write!(f, "{}", err), AnalyzeError::IOError(err) => write!(f, "{}", err), AnalyzeError::ParseError(err) => write!(f, "{}", err), + AnalyzeError::TagsMissing() => write!(f, "Tags could not be found"), } } } diff --git a/modules/ffprobe/src/ffprobe_output.rs b/modules/ffprobe/src/ffprobe_output.rs index a734d55..f305442 100644 --- a/modules/ffprobe/src/ffprobe_output.rs +++ b/modules/ffprobe/src/ffprobe_output.rs @@ -15,11 +15,13 @@ pub struct FFProbeOutputStream { pub codec_type: String, pub height: Option, pub width: Option, + pub tags: Option, } #[derive(Debug, Clone, Deserialize)] pub struct FFProbeOutputFormat { - pub tags: FFProbeOutputTags, + // Some formats don't have tags in the output format but do in the Streams + pub tags: Option, pub duration: String, } diff --git a/modules/ffprobe/src/lib.rs b/modules/ffprobe/src/lib.rs index f8a8a35..7e7e38c 100644 --- a/modules/ffprobe/src/lib.rs +++ b/modules/ffprobe/src/lib.rs @@ -2,7 +2,9 @@ pub mod errors; mod ffprobe_output; pub mod types; -use std::{convert::Into, path::Path, process::Command}; +use std::{path::Path, process::Command}; + +use crate::ffprobe_output::FFProbeOutputTags; use self::errors::{AnalyzeError, FFProbeError}; @@ -47,11 +49,35 @@ fn extract( pub fn analyze( path: &Path, ffprobe_command: Option<&str>, + ignore_missing_tags: bool ) -> Result { let raw_data = extract(path, ffprobe_command)?; + + let tags = match raw_data.format.tags { + Some(tags) => tags, + None => { + let mut found_tags: Option = None; + for stream in raw_data.streams.iter() { + if let Some(tags) = &stream.tags { + found_tags = Some(tags.clone()); + break; + } + } + + match found_tags { + Some(tags) => tags, + None => { + if !ignore_missing_tags { + return Err(AnalyzeError::TagsMissing()); + } + FFProbeOutputTags::default() + } + } + } + }; let mut data = types::FFProbeData { - tags: raw_data.format.tags.into(), + tags: tags.into(), duration: match raw_data.format.duration.parse::() { Ok(ts) => ts, Err(_) => 0.0, diff --git a/src/utils/formats/handlers/ffprobe.rs b/src/utils/formats/handlers/ffprobe.rs index edc9f9e..7fdc3c2 100644 --- a/src/utils/formats/handlers/ffprobe.rs +++ b/src/utils/formats/handlers/ffprobe.rs @@ -32,7 +32,7 @@ pub struct GenericFFMpegAudioFormat { impl GenericFFMpegAudioFormat { fn analyze(&mut self) -> Result<(), BoxedError> { - let output = ffprobe::analyze(&self.path, Some(meta::FFPROBE)); + let output = ffprobe::analyze(&self.path, Some(meta::FFPROBE), false); if let Err(err) = output { return Err(Box::from(err)); diff --git a/src/utils/transcoder/progress_monitor.rs b/src/utils/transcoder/progress_monitor.rs index 920c0cd..bb44531 100644 --- a/src/utils/transcoder/progress_monitor.rs +++ b/src/utils/transcoder/progress_monitor.rs @@ -10,7 +10,7 @@ use std::{ use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher}; fn get_file_length_milliseconds(path: PathBuf) -> Result> { - match ffprobe::analyze(&path, Some(crate::meta::FFPROBE)) { + match ffprobe::analyze(&path, Some(crate::meta::FFPROBE), true) { Ok(data) => Ok((data.duration * 1000.0).round() as u64), Err(e) => Err(Box::from(e)), }