diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 0167f49..ac1e391 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -77,6 +77,10 @@ pub struct Download { #[arg(short, long, default_value_t = false)] pub(crate) yes: bool, + #[arg(help = "Force subtitles to be always burnt-in")] + #[arg(long, default_value_t = false)] + pub(crate) force_hardsub: bool, + #[arg(help = "Url(s) to Crunchyroll episodes or series")] pub(crate) urls: Vec, } @@ -98,8 +102,10 @@ impl Execute for Download { if self.subtitle.is_some() { if let Some(ext) = Path::new(&self.output).extension() { - if ext.to_string_lossy() != "mp4" { - warn!("Detected a non mp4 output container. Adding subtitles may take a while") + if self.force_hardsub { + warn!("Hardsubs are forced. Adding subtitles may take a while") + } else if !["mkv", "mov", "mp4"].contains(&ext.to_string_lossy().as_ref()) { + warn!("Detected a container which does not support softsubs. Adding subtitles may take a while") } } } @@ -137,6 +143,7 @@ impl Execute for Download { let download_builder = DownloadBuilder::new() .default_subtitle(self.subtitle.clone()) + .force_hardsub(self.force_hardsub) .output_format(if is_special_file(&self.output) || self.output == "-" { Some("mpegts".to_string()) } else { diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index dcfcf0a..1e1b207 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -47,6 +47,7 @@ pub struct DownloadBuilder { output_format: Option, audio_sort: Option>, subtitle_sort: Option>, + force_hardsub: bool, } impl DownloadBuilder { @@ -57,6 +58,7 @@ impl DownloadBuilder { output_format: None, audio_sort: None, subtitle_sort: None, + force_hardsub: false, } } @@ -68,6 +70,8 @@ impl DownloadBuilder { audio_sort: self.audio_sort, subtitle_sort: self.subtitle_sort, + force_hardsub: self.force_hardsub, + formats: vec![], } } @@ -92,6 +96,8 @@ pub struct Downloader { audio_sort: Option>, subtitle_sort: Option>, + force_hardsub: bool, + formats: Vec, } @@ -255,8 +261,9 @@ impl Downloader { // this formats are supporting embedding subtitles into the video container instead of // burning it into the video stream directly - let container_supports_softsubs = - ["mkv", "mov", "mp4"].contains(&dst.extension().unwrap_or_default().to_str().unwrap()); + let container_supports_softsubs = !self.force_hardsub + && ["mkv", "mov", "mp4"] + .contains(&dst.extension().unwrap_or_default().to_str().unwrap()); if container_supports_softsubs { for (i, meta) in subtitles.iter().enumerate() { @@ -290,38 +297,39 @@ impl Downloader { .iter() .position(|m| m.language == default_subtitle) { - match dst.extension().unwrap_or_default().to_str().unwrap() { - "mkv" => (), - "mov" | "mp4" => output_presets.extend([ - "-movflags".to_string(), - "faststart".to_string(), - "-c:s".to_string(), - "mov_text".to_string(), - ]), - _ => { - // remove '-c:v copy' and '-c:a copy' from output presets as its causes issues with - // burning subs into the video - let mut last = String::new(); - let mut remove_count = 0; - for (i, s) in output_presets.clone().iter().enumerate() { - if (last == "-c:v" || last == "-c:a") && s == "copy" { - // remove last - output_presets.remove(i - remove_count - 1); - remove_count += 1; - output_presets.remove(i - remove_count); - remove_count += 1; - } - last = s.clone(); - } - - output_presets.extend([ - "-vf".to_string(), - format!( - "ass={}", - subtitles.get(position).unwrap().path.to_str().unwrap() - ), - ]) + if container_supports_softsubs { + match dst.extension().unwrap_or_default().to_str().unwrap() { + "mov" | "mp4" => output_presets.extend([ + "-movflags".to_string(), + "faststart".to_string(), + "-c:s".to_string(), + "mov_text".to_string(), + ]), + _ => (), } + } else { + // remove '-c:v copy' and '-c:a copy' from output presets as its causes issues with + // burning subs into the video + let mut last = String::new(); + let mut remove_count = 0; + for (i, s) in output_presets.clone().iter().enumerate() { + if (last == "-c:v" || last == "-c:a") && s == "copy" { + // remove last + output_presets.remove(i - remove_count - 1); + remove_count += 1; + output_presets.remove(i - remove_count); + remove_count += 1; + } + last = s.clone(); + } + + output_presets.extend([ + "-vf".to_string(), + format!( + "ass={}", + subtitles.get(position).unwrap().path.to_str().unwrap() + ), + ]) } }