fix ffprobe tags extraction on some opus files where tags arent in ffprobe's format but are in streams
This commit is contained in:
parent
fb55fc45b1
commit
9a652001dc
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@ pub struct FFProbeOutputStream {
|
|||
pub codec_type: String,
|
||||
pub height: Option<u16>,
|
||||
pub width: Option<u16>,
|
||||
pub tags: Option<FFProbeOutputTags>,
|
||||
}
|
||||
|
||||
#[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<FFProbeOutputTags>,
|
||||
pub duration: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -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<types::FFProbeData, AnalyzeError> {
|
||||
let raw_data = extract(path, ffprobe_command)?;
|
||||
|
||||
let tags = match raw_data.format.tags {
|
||||
Some(tags) => tags,
|
||||
None => {
|
||||
let mut found_tags: Option<FFProbeOutputTags> = 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::<f64>() {
|
||||
Ok(ts) => ts,
|
||||
Err(_) => 0.0,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::{
|
|||
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
|
||||
fn get_file_length_milliseconds(path: PathBuf) -> Result<u64, Box<dyn std::error::Error>> {
|
||||
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)),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue