improve progress_monitor using out_time_us instead of out_time; use ffprobe crate for duration analysis
This commit is contained in:
parent
dd720c9144
commit
8624dd7a2f
|
@ -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)]
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -183,11 +183,9 @@ fn transcode_file(
|
|||
}
|
||||
};
|
||||
|
||||
if copy_args.skip_same_extension {
|
||||
if config.file_extension.as_ref().unwrap() == &file.extension().unwrap() {
|
||||
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 {
|
||||
|
|
|
@ -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,
|
||||
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)),
|
||||
}
|
||||
|
||||
#[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(
|
||||
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue