aboutsummaryrefslogtreecommitdiff
path: root/transcoder/src
diff options
context:
space:
mode:
Diffstat (limited to 'transcoder/src')
-rw-r--r--transcoder/src/subtitles.rs93
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}")
}