videos
This commit is contained in:
parent
6c6780fc60
commit
f7e0814a38
8 changed files with 206 additions and 92 deletions
|
|
@ -35,3 +35,38 @@ class NarrationLog {
|
|||
}
|
||||
|
||||
export const narrationLog = new NarrationLog();
|
||||
|
||||
function formatVttTimestamp(ms: number): string {
|
||||
const clamped = Math.max(0, Math.round(ms));
|
||||
const totalSeconds = Math.floor(clamped / 1000);
|
||||
const millis = clamped % 1000;
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
const pad = (n: number, width: number): string =>
|
||||
n.toString().padStart(width, '0');
|
||||
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}.${pad(millis, 3)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render narration cues as a WebVTT document.
|
||||
*
|
||||
* Pure helper: takes cues (already ordered by the caller) and produces a
|
||||
* caption sidecar string. Cue text is trimmed and any internal blank lines
|
||||
* are collapsed so a single cue stays a single VTT block.
|
||||
*/
|
||||
export function cuesToVtt(cues: NarrationCue[]): string {
|
||||
let out = 'WEBVTT\n\n';
|
||||
for (const cue of cues) {
|
||||
const start = formatVttTimestamp(cue.videoTimeMs);
|
||||
const end = formatVttTimestamp(cue.videoTimeMs + cue.durationMs);
|
||||
const text = cue.text
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0)
|
||||
.join('\n')
|
||||
.trim();
|
||||
out += `${start} --> ${end}\n${text}\n\n`;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue