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)]
|
#[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)]
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue