improve progress_monitor using out_time_us instead of out_time; use ffprobe crate for duration analysis

This commit is contained in:
chaos 2023-11-12 14:25:37 +00:00
parent dd720c9144
commit 8624dd7a2f
No known key found for this signature in database
6 changed files with 24 additions and 62 deletions

View file

@ -20,6 +20,7 @@ pub struct FFProbeOutputStream {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct FFProbeOutputFormat { pub struct FFProbeOutputFormat {
pub tags: FFProbeOutputTags, pub tags: FFProbeOutputTags,
pub duration: String,
} }
#[derive(Default, Debug, Clone, Deserialize)] #[derive(Default, Debug, Clone, Deserialize)]

View file

@ -50,6 +50,10 @@ pub fn analyze(
let mut data = types::FFProbeData { let mut data = types::FFProbeData {
tags: raw_data.format.tags.into(), tags: raw_data.format.tags.into(),
duration: match raw_data.format.duration.parse::<f64>() {
Ok(ts) => ts,
Err(_) => 0.0,
},
album_art: None, album_art: None,
}; };

View file

@ -48,6 +48,8 @@ pub struct FFProbeAlbumArt {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct FFProbeData { pub struct FFProbeData {
// in seconds
pub duration: f64,
pub tags: FFProbeTags, pub tags: FFProbeTags,
pub album_art: Option<FFProbeAlbumArt>, pub album_art: Option<FFProbeAlbumArt>,
} }

View file

@ -183,11 +183,9 @@ fn transcode_file(
} }
}; };
if copy_args.skip_same_extension { if copy_args.skip_same_extension && config.file_extension.as_ref().unwrap() == &file.extension().unwrap() {
if config.file_extension.as_ref().unwrap() == &file.extension().unwrap() { return copy_file(file.as_relative_file(), copy_args);
return copy_file(file.as_relative_file(), copy_args); }
}
}
let to_path_dest = PathBuf::from_str(copy_args.dest.as_str()).expect("invalid destination"); let to_path_dest = PathBuf::from_str(copy_args.dest.as_str()).expect("invalid destination");
let to_path = match copy_args.single_directory { let to_path = match copy_args.single_directory {

View file

@ -2,67 +2,18 @@ use std::{
fs, fs,
io::{BufRead, BufReader, Seek, SeekFrom}, io::{BufRead, BufReader, Seek, SeekFrom},
path::PathBuf, path::PathBuf,
process::Command,
sync::mpsc::{self, Sender}, sync::mpsc::{self, Sender},
thread::{self, JoinHandle}, thread::{self, JoinHandle},
time::Duration, time::Duration,
}; };
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher}; use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use serde::Deserialize;
use string_error::static_err;
#[derive(Debug, Clone, Deserialize)] fn get_file_length_milliseconds(path: PathBuf) -> Result<u64, Box<dyn std::error::Error>> {
struct FFProbeOutput { match ffprobe::analyze(&path, Some(crate::meta::FFPROBE)) {
pub format: FFProbeFormat, Ok(data) => Ok((data.duration * 1000.0).round() as u64),
} Err(e) => Err(Box::from(e)),
#[derive(Debug, Clone, Deserialize)]
struct FFProbeFormat {
pub duration: String,
}
fn get_file_length_milliseconds(
source_filepath: PathBuf,
) -> Result<u64, Box<dyn std::error::Error>> {
let output = Command::new(crate::meta::FFPROBE)
.args([
"-v",
"quiet",
"-print_format",
"json",
"-show_format",
&source_filepath.to_string_lossy(),
])
.output()?;
if !output.status.success() {
print!("{:?}", String::from_utf8(output.stderr).unwrap());
return Err(static_err("FFprobe Crashed"));
} }
let output_str = String::from_utf8(output.stdout).unwrap();
let ffprobe_out: FFProbeOutput = serde_json::from_str(output_str.as_str())?;
let duration_seconds = ffprobe_out.format.duration.parse::<f32>()?;
Ok((duration_seconds * 1000.0).round() as u64)
}
fn ffprobe_duration_to_ms(duration: String) -> Result<u64, Box<dyn std::error::Error>> {
let fields: Vec<&str> = duration.split(':').collect();
let mut duration = Duration::from_nanos(0);
let hours = fields[0].parse::<u64>()?;
duration += Duration::from_secs(hours * 60 * 60);
let minutes = fields[1].parse::<u64>()?;
duration += Duration::from_secs(minutes * 60);
let seconds = fields[1].parse::<f64>()?;
duration += Duration::from_millis((seconds * 1000.0) as u64);
Ok(duration.as_millis() as u64)
} }
pub fn progress_monitor( pub fn progress_monitor(
@ -121,13 +72,19 @@ pub fn progress_monitor(
break 'outer; break 'outer;
} }
if ln.starts_with("out_time=") { // there is a out_time_ms however it seems to be the same value as out_time_us
let out_time = ln.strip_prefix("out_time=").unwrap().to_string(); // https://trac.ffmpeg.org/ticket/7345
let out_time_ms = ffprobe_duration_to_ms(out_time).unwrap(); // it has not yet been actually fixed
if ln.starts_with("out_time_us=") {
let out_time = ln.strip_prefix("out_time_us=").unwrap().to_string();
let out_time_ms = match out_time.parse::<u64>() {
Ok(ts) => ((ts as f64) / 1000.0).round(),
Err(_) => 0.0,
};
if sender if sender
.send(format!( .send(format!(
"{:.2}%", "{:.2}%",
((out_time_ms as f64 / total_length_millis as f64) * 100.0) ((out_time_ms / total_length_millis as f64) * 100.0)
)) ))
.is_err() .is_err()
{ {