From 7e3ebef125214c8204220e4a3be9a0172bf234d6 Mon Sep 17 00:00:00 2001 From: kcfancher Date: Thu, 2 Apr 2026 06:18:55 -0400 Subject: [PATCH] Move subtitle parsing into a shared interface [Modified from e84404b7857f8c611eda7a65b5d61ee6c9823d75, 2026-03-28 09:52:31 -0400] Extracted the srt specific extraction behind a generic shared interface to allow easier adding of other subtitle formats in the future. --- .../editor/panels/assets/views/captions.tsx | 7 ++-- apps/web/src/lib/subtitles/parse.ts | 33 +++++++++++++++++++ apps/web/src/lib/subtitles/srt.ts | 8 ++--- 3 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 apps/web/src/lib/subtitles/parse.ts diff --git a/apps/web/src/components/editor/panels/assets/views/captions.tsx b/apps/web/src/components/editor/panels/assets/views/captions.tsx index 304fbf43..137d1baf 100644 --- a/apps/web/src/components/editor/panels/assets/views/captions.tsx +++ b/apps/web/src/components/editor/panels/assets/views/captions.tsx @@ -23,7 +23,7 @@ import { transcriptionService } from "@/services/transcription/service"; import { decodeAudioToFloat32 } from "@/lib/media/audio"; import { buildCaptionChunks } from "@/lib/transcription/caption"; import { insertCaptionChunksAsTextTrack } from "@/lib/subtitles/insert"; -import { parseSrt } from "@/lib/subtitles/srt"; +import { parseSubtitleFile } from "@/lib/subtitles/parse"; import { Spinner } from "@/components/ui/spinner"; import { Section, @@ -121,7 +121,10 @@ export function Captions() { setProcessingStep("Reading subtitle file..."); const input = await file.text(); - const result = parseSrt({ input }); + const result = parseSubtitleFile({ + fileName: file.name, + input, + }); if (result.captions.length === 0) { throw new Error("No valid subtitle cues were found in the .srt file"); diff --git a/apps/web/src/lib/subtitles/parse.ts b/apps/web/src/lib/subtitles/parse.ts new file mode 100644 index 00000000..5f5d07cc --- /dev/null +++ b/apps/web/src/lib/subtitles/parse.ts @@ -0,0 +1,33 @@ +import type { CaptionChunk } from "@/lib/transcription/types"; +import { parseSrt } from "./srt"; + +export interface ParseSubtitleResult { + captions: CaptionChunk[]; + skippedCueCount: number; +} + +export function parseSubtitleFile({ + fileName, + input, +}: { + fileName: string; + input: string; +}): ParseSubtitleResult { + const extension = getFileExtension({ fileName }); + + switch (extension) { + case "srt": + return parseSrt({ input }); + default: + throw new Error("Unsupported subtitle format"); + } +} + +function getFileExtension({ + fileName, +}: { + fileName: string; +}): string { + const extension = fileName.split(".").pop(); + return extension?.toLowerCase() ?? ""; +} diff --git a/apps/web/src/lib/subtitles/srt.ts b/apps/web/src/lib/subtitles/srt.ts index 6ac939cc..a5377b0b 100644 --- a/apps/web/src/lib/subtitles/srt.ts +++ b/apps/web/src/lib/subtitles/srt.ts @@ -1,19 +1,15 @@ import type { CaptionChunk } from "@/lib/transcription/types"; +import type { ParseSubtitleResult } from "./parse"; const TIMESTAMP_SEPARATOR = /\s*-->\s*/; const TIMESTAMP_PATTERN = /^(\d{2}:\d{2}:\d{2}[,.]\d{1,3})\s*-->\s*(\d{2}:\d{2}:\d{2}[,.]\d{1,3})/; -export interface ParseSrtResult { - captions: CaptionChunk[]; - skippedCueCount: number; -} - export function parseSrt({ input, }: { input: string; -}): ParseSrtResult { +}): ParseSubtitleResult { const normalized = input.replace(/\r\n?/g, "\n").trim(); if (!normalized) { return {