use std::{
fs,
path::Path,
process::Command,
sync::atomic::{AtomicBool, Ordering},
sync::Arc,
time::Duration,
};
use super::Result;
pub fn extract_audio(
input: &Path,
output: &Path,
running: &Arc<AtomicBool>,
) -> Result<()> {
let input = input.to_str().ok_or("Input invalid Unicode")?;
let output = output.to_str().ok_or("Output invalid Unicode")?;
let output = Command::new("ffmpeg")
.args(&[
"-y", "-i", input, "-vn", "-c:a", "aac", "-b:a", "192k", output,
])
.output()?;
if !output.status.success() && running.load(Ordering::SeqCst) {
return Err("Failed extracting audio".into());
}
Ok(())
}
pub fn split_video(
input: &Path,
output_dir: &Path,
segment_length: Duration,
running: &Arc<AtomicBool>,
) -> Result<()> {
let extension = input
.extension()
.ok_or("Unable to find extension")?
.to_str()
.ok_or("Unable to convert OsString extension")?;
let input = input.to_str().ok_or("Input invalid Unicode")?;
let mut output_dir = output_dir.to_path_buf();
output_dir.push(format!("chunk_%03d.{}", extension));
let output = output_dir.to_str().ok_or("Output invalid Unicode")?;
let output = Command::new("ffmpeg")
.args(&[
"-y",
"-i",
input,
"-an",
"-c",
"copy",
"-f",
"segment",
"-segment_time",
&segment_length.as_secs().to_string(),
output,
])
.output()?;
if !output.status.success() && running.load(Ordering::SeqCst) {
return Err("Failed splitting video".into());
}
Ok(())
}
pub fn combine(
encoded_dir: &Path,
audio: &Path,
output: &Path,
running: &Arc<AtomicBool>,
) -> Result<()> {
let mut chunks = fs::read_dir(&encoded_dir)?
.map(|res| res.and_then(|readdir| Ok(readdir.path())))
.map(|res| res.map_err(|e| e.into()))
.map(|res| res.and_then(|path| Ok(path.into_os_string())))
.map(|res| {
res.and_then(|os_string| {
os_string
.into_string()
.map_err(|_| "Failed OsString conversion".into())
})
})
.map(|res| res.and_then(|file| Ok(format!("file '{}'\n", file))))
.collect::<Result<Vec<String>>>()?;
chunks.sort();
let chunks = chunks.join("");
let mut file_list = encoded_dir.to_path_buf();
file_list.push("files.txt");
fs::write(&file_list, chunks)?;
let audio = audio.to_str().ok_or("Audio invalid Unicode")?;
let file_list = file_list.to_str().ok_or("File list invalid Unicode")?;
let output = output.to_str().ok_or("Output invalid Unicode")?;
let output = Command::new("ffmpeg")
.args(&[
"-y",
"-f",
"concat",
"-safe",
"0",
"-i",
file_list,
"-i",
audio,
"-c",
"copy",
"-movflags",
"+faststart",
output,
])
.output()?;
if !output.status.success() && running.load(Ordering::SeqCst) {
return Err("Failed combining video".into());
}
Ok(())
}