From 85e471962086afd74ee507ef05f49fd4db3e053e Mon Sep 17 00:00:00 2001 From: Thomas Gotwig Date: Sun, 26 May 2024 19:42:47 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20Add=20--verbose=20(major=20loggi?= =?UTF-8?q?ng=20changes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/tgotwig/vidmerger/issues/26 --- CHANGELOG.md | 6 +++ README.md | 3 +- src/cli.rs | 4 ++ src/commanders/_cmd.rs | 74 +++++++++++++++++++++++++++++------ src/commanders/chapterer.rs | 26 ++++++++---- src/commanders/fps_changer.rs | 55 ++++++++++++++++---------- src/commanders/merger.rs | 12 +++--- src/helpers/io_helper.rs | 16 +++++--- src/main.rs | 21 ++++++---- tests/integration.rs | 1 + 10 files changed, 157 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41d1313..264984d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## šŸŽ‰ [Unreleased] + +### Added + +- **--verbose** which prints detailed logs. + ## šŸŽ‰ [0.3.2] - 2024-01-14 ### Added diff --git a/README.md b/README.md index 466d8aa..9a64656 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,8 @@ OPTIONS: --skip-chapterer Skips the chapterer --skip-fps-changer Skips the fps changer --skip-wait Skips the wait time for reading - -V, --version Print version information``` + -V, --version Print version information + --verbose Prints detailed logs ``` ## āœØ Installing / Getting started diff --git a/src/cli.rs b/src/cli.rs index e1cdae3..b72fcb1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -42,6 +42,10 @@ impl Cli { .long("skip-wait") .help("Skips the wait time for reading") ) + .arg(Arg::new("verbose") + .long("verbose") + .help("Prints detailed logs") + ) .arg_required_else_help(true) .get_matches(); diff --git a/src/commanders/_cmd.rs b/src/commanders/_cmd.rs index 4b9b226..db0f0bb 100644 --- a/src/commanders/_cmd.rs +++ b/src/commanders/_cmd.rs @@ -1,19 +1,28 @@ +use crate::cli::Cli; +use path_slash::PathBufExt; use std::{ io::Error, path::PathBuf, process::{Child, Command, Output, Stdio}, }; +use term_painter::Color::BrightBlue; +use term_painter::ToStyle; -use path_slash::PathBufExt; +pub fn merge(input: String, output: &String) -> Result { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); -pub fn merge(input: String, output: String) -> Result { let cmd = format!( "ffmpeg -y -f concat -safe 0 -i {} -map 0 -c copy {}", input, output ); - println!("šŸš€ Start Merger, calling: `{}`\n", cmd); - execute_cmd(cmd) + println!("šŸš€ Run Merger, calling: {}", BrightBlue.paint(&cmd)); + if verbose { + execute_cmd(cmd) + } else { + execute_cmd_silently(cmd) + } } pub fn merge_with_chapters( @@ -21,6 +30,9 @@ pub fn merge_with_chapters( file_path: PathBuf, output_file_for_chapterer: &str, ) -> Result { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); + let cmd = format!( "ffmpeg -y -i {} -i {} -map 0 -map_metadata 1 -codec copy {}", &input_file_for_chapterer, @@ -28,10 +40,12 @@ pub fn merge_with_chapters( output_file_for_chapterer ); - println!("šŸš€ Calling:\n"); - println!("- {}\n", cmd); - - execute_cmd(cmd) + println!("šŸ“– Run Chapterer, calling: {}", BrightBlue.paint(&cmd)); + if verbose { + execute_cmd(cmd) + } else { + execute_cmd_silently(cmd) + } } pub fn run_ffmpeg_info_command(file_to_merge: &PathBuf) -> Result { @@ -45,27 +59,47 @@ pub fn adjust_fps_by_ffmpeg( fps_goal: &f32, new_file_location: PathBuf, ) -> PathBuf { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); + let cmd = format!( "ffmpeg -i {} -r {} {}", file_to_merge.to_str().unwrap(), fps_goal, new_file_location.to_str().unwrap() ); - println!("- {}", cmd); + println!("šŸš€ Start FPS Changer, calling: {}", BrightBlue.paint(&cmd)); + + // let res = execute_cmd(cmd).unwrap().wait_with_output(); + // println!("{:?}", res); - let res = execute_cmd(cmd).unwrap().wait_with_output(); - println!("{:?}", res); + if verbose { + let res = execute_cmd(cmd).unwrap().wait_with_output(); + println!("{:?}", res); + } else { + execute_cmd_silently(cmd) + .unwrap() + .wait_with_output() + .unwrap(); + } new_file_location } pub fn get_media_seconds(media_path: &str) -> Result> { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); + let cmd = format!( "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 '{}'", media_path ); - println!("šŸš€ Calling:\n"); - println!("- {}\n", cmd); + if verbose { + println!( + "šŸ“– Getting media seconds, calling: {}", + BrightBlue.paint(&cmd) + ); + } let res = execute_cmd(cmd); let output = res.unwrap().wait_with_output().unwrap(); @@ -86,3 +120,17 @@ fn execute_cmd(cmd: String) -> Result { .stdout(Stdio::piped()) .spawn() } + +fn execute_cmd_silently(cmd: String) -> Result { + let (interpreter, arg) = if cfg!(target_os = "windows") { + ("powershell", "/c") + } else { + ("sh", "-c") + }; + Command::new(interpreter) + .arg(arg) + .arg(cmd) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() +} diff --git a/src/commanders/chapterer.rs b/src/commanders/chapterer.rs index f89d9af..bf2eb49 100644 --- a/src/commanders/chapterer.rs +++ b/src/commanders/chapterer.rs @@ -5,6 +5,8 @@ use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; use std::str; +use term_painter::Color::BrightBlue; +use term_painter::ToStyle; pub fn execute( files_to_merge_as_strings: Vec, @@ -12,9 +14,6 @@ pub fn execute( ffmpeg_output_file: PathBuf, file_format: &String, ) { - println!("----------------------------------------------------------------"); - println!("šŸ“– Start Chapterer\n"); - let mut start_time = 0; let mut metadata_string = String::from(";FFMETADATA1\n"); @@ -40,7 +39,8 @@ pub fn execute( let input_file_for_chapterer: String = ffmpeg_output_file.to_slash().unwrap().to_string(); let mut output_with_chapters = ffmpeg_output_file.clone(); - output_with_chapters.set_file_name(format!("output_with_chapters.{}", file_format)); + let output_file_name = format!("output_with_chapters.{}", file_format); + output_with_chapters.set_file_name(&output_file_name); let output_file_for_chapterer: String = output_with_chapters.to_slash().unwrap().to_string(); _cmd::merge_with_chapters( @@ -51,11 +51,23 @@ pub fn execute( .unwrap() .wait_with_output() .unwrap(); + println!( + "āœ… Successfully generated: {}", + BrightBlue.paint(&output_file_for_chapterer) + ); fs::remove_file(Path::new(&input_file_for_chapterer)).unwrap(); - fs::rename(output_file_for_chapterer, ffmpeg_output_file).unwrap(); - - println!("āœ… Video with chapters created successfully."); + println!( + "āœ… Successfully deleted: {}", + BrightBlue.paint(&input_file_for_chapterer) + ); + + fs::rename(&output_file_for_chapterer, ffmpeg_output_file).unwrap(); + println!( + "āœ… Successfully renamed: {} to {}", + BrightBlue.paint(output_file_for_chapterer), + BrightBlue.paint(input_file_for_chapterer) + ); } fn extract_title(path: &str, file_format: &str) -> String { diff --git a/src/commanders/fps_changer.rs b/src/commanders/fps_changer.rs index 9742a6d..8acda13 100644 --- a/src/commanders/fps_changer.rs +++ b/src/commanders/fps_changer.rs @@ -1,5 +1,6 @@ use super::fps_reader::get_fps; use crate::{ + cli::Cli, commanders, helpers::{ io_helper::path_bufs_to_sorted_strings, str_helper::gen_input_file_content_for_ffmpeg, @@ -15,6 +16,9 @@ pub fn change_fps( tmp_dir: &Path, fps_from_cli: f32, ) -> (Vec, Vec, std::string::String) { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); + let mut new_files_to_merge = Vec::new(); let mut map: HashMap<&PathBuf, f32> = HashMap::new(); @@ -32,44 +36,53 @@ pub fn change_fps( let set: HashSet = map.values().map(|value| value.to_string()).collect(); let files_to_merge = if set.len() > 1 { - println!("----------------------------------------------------------------"); - println!("šŸ”Ž FPS mismatches detected"); - println!(); - println!("Will be merged directly: \n"); - let mut output = Vec::new(); + let mut output_directly = Vec::new(); for (key, value) in &map { if value == &fps_goal { - output.push(format!( + output_directly.push(format!( "- {} ({} fps)", key.file_name().unwrap().to_string_lossy(), value )); } } - output.sort(); - for line in output { - println!("{}", line); - } - println!(); - println!("Will be merged indirectly, generating new files from listed below with {} fps and merges with listed above:", fps_goal); - println!(); - let mut output = Vec::new(); + output_directly.sort(); + + let mut output_indirectly = Vec::new(); for (key, value) in &map { if value != &fps_goal { - output.push(format!( + output_indirectly.push(format!( "- {} ({} fps)", key.file_name().unwrap().to_string_lossy(), value )); } } - output.sort(); - for line in output { - println!("{}", line); + output_indirectly.sort(); + + println!( + "šŸ”Ž FPS mismatches detected ({:?}), scaling to {} fps: {}/{}", + set, + fps_goal, + output_indirectly.len(), + set.len() + ); + + if verbose { + println!(); + println!("Will be merged directly: \n"); + for line in output_directly { + println!("{}", line); + } + println!(); + println!("Will be merged indirectly, generating new files from listed below with {} fps and merges with listed above:", fps_goal); + println!(); + for line in output_indirectly { + println!("{}", line); + } + println!(); } - println!("----------------------------------------------------------------"); - println!("šŸš€ Start FPS Changer, calling:"); - println!(); + for file_to_merge in files_to_merge { let fps = get_fps(&file_to_merge); diff --git a/src/commanders/merger.rs b/src/commanders/merger.rs index f943d15..6908f34 100644 --- a/src/commanders/merger.rs +++ b/src/commanders/merger.rs @@ -1,16 +1,14 @@ use crate::commanders::_cmd; +use term_painter::Color::BrightBlue; +use term_painter::ToStyle; -pub fn merge(input: String, output: String, file_format: &String) { - let child = _cmd::merge(input, output); +pub fn merge(input: String, output: String) { + let child = _cmd::merge(input, &output); let res = child.unwrap().wait_with_output(); - println!("{:?}", res); - println!("----------------------------------------------------------------"); if res.is_ok() { - println!("āœ… Successfully generated:"); - println!(); - println!("- output.{}", file_format); + println!("āœ… Successfully generated: {}", BrightBlue.paint(output)); } else { panic!("āŒ Something went wrong: \n\n{}", res.unwrap_err()); } diff --git a/src/helpers/io_helper.rs b/src/helpers/io_helper.rs index 48b23e1..ead39d4 100644 --- a/src/helpers/io_helper.rs +++ b/src/helpers/io_helper.rs @@ -5,6 +5,8 @@ use std::io::{Result, Write}; use std::path::{Path, PathBuf}; use std::process::exit; +use crate::cli::Cli; + pub fn exit_when_ffmpeg_not_available() { if which::which("ffmpeg").is_err() { eprintln!("āŒ ffmpeg is not available. Please install it first."); @@ -13,12 +15,16 @@ pub fn exit_when_ffmpeg_not_available() { } pub fn remove_file(path: &Path) -> Result<()> { + let matches = Cli::init().get_matches(); + let verbose: bool = matches.is_present("verbose"); + if Path::new(path).exists() { - println!("----------------------------------------------------------------"); - print!( - "šŸ—‘ļø Removing old data:\n\n- {}", - path.file_name().unwrap().to_string_lossy() - ); + if verbose { + print!( + "šŸ—‘ļø Removing old data: `{}`", + path.file_name().unwrap().to_string_lossy() + ); + } fs::remove_file(path)?; } Ok(()) diff --git a/src/main.rs b/src/main.rs index f69ca64..9b6e16a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,8 @@ use std::io::Error; use std::path::Path; use std::thread; use system_shutdown::shutdown; +use term_painter::Color::BrightBlue; +use term_painter::ToStyle; fn main() -> Result<(), Error> { let matches = Cli::init().get_matches(); @@ -31,6 +33,7 @@ fn main() -> Result<(), Error> { let skip_fps_changer = matches.is_present("skip-fps-changer"); let skip_chapterer = matches.is_present("skip-chapterer"); let skip_wait = matches.is_present("skip-wait"); + let verbose: bool = matches.is_present("verbose"); let fps_from_cli = matches .value_of("fps") .unwrap_or("0") @@ -46,12 +49,13 @@ fn main() -> Result<(), Error> { select(target_dir, &file_format); if !ffmpeg_input_content.is_empty() { - println!("\n----------------------------------------------------------------"); - println!("šŸ“œ Order of merging:\n"); - println!("{}\n", create_order_of_merging(&ffmpeg_input_content)); - if !skip_wait { - println!("\nā³ Waiting 3 seconds to read"); - thread::sleep(time::Duration::from_secs(3)); + if verbose { + println!("\n\nšŸ“œ Order of merging:\n"); + println!("{}\n", create_order_of_merging(&ffmpeg_input_content)); + if !skip_wait { + println!("\nā³ Waiting 3 seconds to read"); + thread::sleep(time::Duration::from_secs(3)); + } } let tmp_dir = create_tmp_dir(); @@ -63,11 +67,14 @@ fn main() -> Result<(), Error> { let ffmpeg_input_file = tmp_dir.join("ffmpeg_input_file.txt"); create(&ffmpeg_input_file, ffmpeg_input_content); + println!( + "āœ… Successfully generated: {} (contains merge order)", + BrightBlue.paint(ffmpeg_input_file.to_slash().unwrap()) + ); commanders::merger::merge( ffmpeg_input_file.to_slash().unwrap(), ffmpeg_output_file.to_slash().unwrap().to_string(), - &file_format, ); if !skip_chapterer { diff --git a/tests/integration.rs b/tests/integration.rs index 197a276..e953a00 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -104,6 +104,7 @@ mod integration { Command::cargo_bin(BIN) .unwrap() .arg("--skip-wait") + .arg("--verbose") .arg(format!("data/{}", test_name)) .assert() .success(),