import { buildCaptionWords, buildCaptionLines, type CaptionLine } from "./captions"; import type { EDLItem, Word } from "./timeline-model"; const pad = (n: number, w = 2) => String(n).padStart(w, "0"); // HH:MM:SS,mmm (SRT, comma) or HH:MM:SS.mmm (VTT, dot) const clock = (ms: number, sep: "," | ".") => { const t = Math.max(0, Math.round(ms)); const h = Math.floor(t / 3600000), m = Math.floor((t % 3600000) / 60000), s = Math.floor((t % 60000) / 1000); return `${pad(h)}:${pad(m)}:${pad(s)}${sep}${pad(t % 1000, 3)}`; }; export const captionLinesFor = (edl: EDLItem[], wordsById: Record): CaptionLine[] => buildCaptionLines(buildCaptionWords(edl, wordsById)); const lineText = (l: CaptionLine) => l.words.map((w) => w.text).join(" ").trim(); export function toSRT(lines: CaptionLine[]): string { return lines.filter(lineText).map((l, i) => `${i + 1}\n${clock(l.startMs, ",")} --> ${clock(l.endMs, ",")}\n${lineText(l)}` ).join("\n\n") + "\n"; } export function toVTT(lines: CaptionLine[]): string { return "WEBVTT\n\n" + lines.filter(lineText).map((l) => `${clock(l.startMs, ".")} --> ${clock(l.endMs, ".")}\n${lineText(l)}` ).join("\n\n") + "\n"; } export function downloadFile(name: string, content: BlobPart, type: string) { const url = URL.createObjectURL(new Blob([content], { type })); const a = document.createElement("a"); a.href = url; a.download = name; document.body.appendChild(a); a.click(); a.remove(); setTimeout(() => URL.revokeObjectURL(url), 1000); }