use crate::subtitles::MP4Subtitles;
use anyhow::{anyhow, bail, Result};
use clap::{Args, ValueEnum};
#[derive(Debug, Clone, ValueEnum)]
pub enum Format {
Srt,
Vtt,
}
#[derive(Debug, Clone, Args)]
pub struct Extract {
#[arg(required = true)]
files: Vec<String>,
#[arg(short, long, value_enum, default_value_t = Format::Srt)]
format: Format,
#[arg(short, long)]
timescale: Option<u32>,
}
impl Extract {
pub fn perform(&self) -> Result<()> {
let mut files = vec![];
for pattern in &self.files {
for file in glob::glob(pattern)? {
files.push(file?);
}
}
if files.is_empty() {
bail!("at least one file is required to extract subtitles")
}
let subtitles = if files.len() == 1 {
let split_data =
mp4decrypt::mp4split(&std::fs::read(&files[0])?).map_err(|x| anyhow!(x))?;
let mut subtitles =
MP4Subtitles::new(&split_data[0], self.timescale).map_err(|x| anyhow!(x))?;
for data in &split_data[1..] {
subtitles.add_cue(data).map_err(|x| anyhow!(x))?;
}
subtitles.to_subtitles()
} else {
let mut subtitles = MP4Subtitles::new(&std::fs::read(&files[0])?, self.timescale)
.map_err(|x| anyhow!(x))?;
for file in &files[1..] {
subtitles
.add_cue(&std::fs::read(file)?)
.map_err(|x| anyhow!(x))?;
}
subtitles.to_subtitles()
};
print!(
"{}",
match &self.format {
Format::Srt => subtitles.to_srt(),
Format::Vtt => subtitles.to_vtt(),
}
);
Ok(())
}
}