fix ffprobe tags extraction on some opus files where tags arent in ffprobe's format but are in streams

This commit is contained in:
chaos 2023-11-12 15:58:32 +00:00
parent fb55fc45b1
commit 9a652001dc
No known key found for this signature in database
5 changed files with 35 additions and 5 deletions

View file

@ -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"),
}
}
}

View file

@ -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,
}

View file

@ -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,

View file

@ -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));

View file

@ -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)),
}