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)]
pub struct FFProbeOutputFormat {
pub tags: FFProbeOutputTags,
pub duration: String,
}
#[derive(Default, Debug, Clone, Deserialize)]

View file

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

View file

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

View file

@ -183,11 +183,9 @@ fn transcode_file(
}
};
if copy_args.skip_same_extension {
if config.file_extension.as_ref().unwrap() == &file.extension().unwrap() {
return copy_file(file.as_relative_file(), copy_args);
}
}
if copy_args.skip_same_extension && config.file_extension.as_ref().unwrap() == &file.extension().unwrap() {
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 = match copy_args.single_directory {

View file

@ -2,67 +2,18 @@ use std::{
fs,
io::{BufRead, BufReader, Seek, SeekFrom},
path::PathBuf,
process::Command,
sync::mpsc::{self, Sender},
thread::{self, JoinHandle},
time::Duration,
};
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use serde::Deserialize;
use string_error::static_err;
#[derive(Debug, Clone, Deserialize)]
struct FFProbeOutput {
pub format: FFProbeFormat,
}
#[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"));
fn get_file_length_milliseconds(path: PathBuf) -> Result<u64, Box<dyn std::error::Error>> {
match ffprobe::analyze(&path, Some(crate::meta::FFPROBE)) {
Ok(data) => Ok((data.duration * 1000.0).round() as u64),
Err(e) => Err(Box::from(e)),
}
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(
@ -121,13 +72,19 @@ pub fn progress_monitor(
break 'outer;
}
if ln.starts_with("out_time=") {
let out_time = ln.strip_prefix("out_time=").unwrap().to_string();
let out_time_ms = ffprobe_duration_to_ms(out_time).unwrap();
// there is a out_time_ms however it seems to be the same value as out_time_us
// https://trac.ffmpeg.org/ticket/7345
// 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
.send(format!(
"{:.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()
{