diff options
Diffstat (limited to 'transcoder')
-rw-r--r-- | transcoder/src/subtitles.rs | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/transcoder/src/subtitles.rs b/transcoder/src/subtitles.rs index a2546f4..1fea3cf 100644 --- a/transcoder/src/subtitles.rs +++ b/transcoder/src/subtitles.rs @@ -4,52 +4,87 @@ Copyright (C) 2024 metamuffin <metamuffin.org> */ use anyhow::anyhow; +use jellycommon::jhls::SubtitleCue; use std::fmt::Write; // TODO discontinued for now. since this should be snippetized aswell. -pub fn webvtt_from_ass_blocks( - title: String, - _codec_private: Vec<u8>, - blocks: Vec<(u64, u64, Vec<u8>)>, -) -> anyhow::Result<String> { +pub fn write_webvtt(title: String, subtitles: Vec<SubtitleCue>) -> anyhow::Result<String> { let mut out = String::new(); writeln!(out, "WEBVTT - {title}")?; // TODO ensure title does not contain "-->" writeln!(out)?; - - for (pts, dur, block) in blocks { - let block = String::from_utf8(block)?; - let text = convert_block(&block).ok_or(anyhow!("bad ass xD"))?; - writeln!(out, "{} --> {}", format_time(pts), format_time(pts + dur))?; - writeln!(out, "- {text}")?; + for SubtitleCue { + start, + end, + content, + } in subtitles + { + writeln!(out, "{} --> {}", format_time(start), format_time(end))?; + writeln!(out, "- {content}")?; writeln!(out)?; } + Ok(out) +} +pub fn parse_webvtt_blocks(blocks: Vec<(u64, u64, Vec<u8>)>) -> anyhow::Result<Vec<SubtitleCue>> { + let mut out = Vec::new(); + for (pts, dur, block) in blocks { + let content = String::from_utf8_lossy(&block).trim().to_string(); + out.push(SubtitleCue { + content, + start: pts as f64 / 1000., + end: (pts + dur) as f64 / 1000., + }) + } Ok(out) } -fn format_time(t: u64) -> String { - let t = t as f64 / 1_000_000.; +pub fn parse_ass_blocks( + _codec_private: Vec<u8>, + blocks: Vec<(u64, u64, Vec<u8>)>, +) -> anyhow::Result<Vec<SubtitleCue>> { + // TODO dont ignore codec_private - // let mmm = (t.fract() * 1000.).floor(); - // let mmm = ((t * 60.).fract() * 60.).floor(); - // let mmm = ((t / 60).fract() * 60.).floor(); + fn convert_block(s: &str) -> Option<&str> { + // ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text + let (_read_order, s) = s.split_once(',')?; + let (_layer, s) = s.split_once(',')?; + let (_style, s) = s.split_once(',')?; + let (_name, s) = s.split_once(',')?; + let (_marginl, s) = s.split_once(',')?; + let (_marginr, s) = s.split_once(',')?; + let (_marginv, s) = s.split_once(',')?; + let (_effect, text) = s.split_once(',')?; - // format!("{hh:4}:{mm:02}:{ss:02}.{mmm:03}") - format!("{t}") + Some(text) + } + + let mut out = Vec::new(); + for (pts, dur, block) in blocks { + let block = String::from_utf8(block)?; + let text = convert_block(&block).ok_or(anyhow!("bad ass xD"))?; + out.push(SubtitleCue { + content: text.to_owned(), + start: pts as f64 / 1000., + end: (pts + dur) as f64 / 1000., + }) + } + Ok(out) } -fn convert_block(s: &str) -> Option<&str> { - // ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text - let (_read_order, s) = s.split_once(',')?; - let (_layer, s) = s.split_once(',')?; - let (_style, s) = s.split_once(',')?; - let (_name, s) = s.split_once(',')?; - let (_marginl, s) = s.split_once(',')?; - let (_marginr, s) = s.split_once(',')?; - let (_marginv, s) = s.split_once(',')?; - let (_effect, text) = s.split_once(',')?; +fn format_time(t: f64) -> String { + const SECOND: u64 = 1000; + const MINUTE: u64 = SECOND * 60; + const HOUR: u64 = MINUTE * 60; + + let t = (t * 1000.) as u64; + let hh = t / HOUR; + let t = t % HOUR; + let mm = t / MINUTE; + let t = t % MINUTE; + let ss = t / SECOND; + let mmm = t % SECOND; - Some(text) + format!("{hh:04}:{mm:02}:{ss:02}.{mmm:03}") } |