Files
ttstd-infinite-canvas/web/src/lib/timeline/srt-parser.ts
爱笑的毛毛虫 43e65570a5 feat(canvas): 新增视频节点字幕体系与多轨时间线编辑(关联 #187) (#191)
* fix(ci): 后端测试 - 修复 responses 流式测试数据与 Grok 生图测试 SSRF 放行

* feat(canvas): 新增视频节点字幕体系与多轨时间线编辑(关联 #187)

---------

Co-authored-by: zhaoyue <zhaoyue@rongshantech.com>
2026-08-08 18:28:28 +08:00

68 lines
2.2 KiB
TypeScript

import type { SrtEntry } from "@/types/timeline";
function timeToMs(timestamp: string): number {
const [hours, minutes, secondsAndMs] = timestamp.split(":");
const [seconds, milliseconds] = secondsAndMs.split(",");
return Number.parseInt(hours, 10) * 3_600_000 + Number.parseInt(minutes, 10) * 60_000 + Number.parseInt(seconds, 10) * 1_000 + Number.parseInt(milliseconds, 10);
}
export function parseSrt(content: string): SrtEntry[] {
if (!content.trim()) {
return [];
}
const blocks = content.trim().split(/\r?\n\s*\r?\n/);
const entries: SrtEntry[] = [];
for (const block of blocks) {
const lines = block.trim().split(/\r?\n/);
if (lines.length < 3) {
continue;
}
const index = Number.parseInt(lines[0], 10);
if (Number.isNaN(index)) {
continue;
}
const match = lines[1].match(/\d{2}:\d{2}:\d{2},\d{3}\s*-->\s*\d{2}:\d{2}:\d{2},\d{3}/);
if (!match) {
continue;
}
const [start, end] = match[0].split(/\s*-->\s*/);
entries.push({
index,
startMs: timeToMs(start),
endMs: timeToMs(end),
text: lines.slice(2).join("\n"),
});
}
return entries;
}
function msToTimestamp(ms: number): string {
const safeMs = Math.max(0, Math.round(ms));
const hours = Math.floor(safeMs / 3_600_000);
const minutes = Math.floor((safeMs % 3_600_000) / 60_000);
const seconds = Math.floor((safeMs % 60_000) / 1_000);
const milliseconds = safeMs % 1_000;
return `${String(hours).padStart(2, "0")}:` + `${String(minutes).padStart(2, "0")}:` + `${String(seconds).padStart(2, "0")},` + `${String(milliseconds).padStart(3, "0")}`;
}
export function serializeSrtEntries(entries: SrtEntry[]): string {
if (entries.length === 0) {
return "";
}
return (
entries
.map((entry, idx) => {
const index = Number.isInteger(entry.index) && entry.index > 0 ? entry.index : idx + 1;
return `${index}\n${msToTimestamp(entry.startMs)} --> ${msToTimestamp(entry.endMs)}\n${entry.text}`;
})
.join("\n\n") + "\n"
);
}