Written by: Marlon Colca
Posted on 11 Sep 2025 - 23 days ago
nextjs typescript clones
Add support for .srt subtitles by converting them to WebVTT on the fly, so the native browser player can render captions without extra tooling.
.srt subtitles by converting them to WebVTT on the fly, so the native browser player can render captions without extra tooling.src/lib/subtitles.ts: helpers — isSrtUrl, srtToVtt, and processSubtitles.src/hooks/useSubtitles.ts: fetches .srt, converts to VTT, and returns processed tracks.src/components/VideoPlayer.tsx: uses useSubtitles() and renders <track> elements.// src/lib/subtitles.ts
export function srtToVtt(srt: string): string {
const text = srt.replace(/^\uFEFF/, "");
const blocks = text
.replace(/\r\n/g, "\n")
.replace(/\r/g, "\n")
.split(/\n\n+/);
const out: string[] = ["WEBVTT", ""];
for (const block of blocks) {
const lines = block.split("\n").filter((l) => l.trim() !== "");
if (!lines.length) continue;
let i = 0;
if (/^\d+$/.test(lines[0].trim())) i = 1; // optional index
if (!lines[i]) continue;
const time = lines[i]
.replace(/,/, ".")
.replace(/ --> .*?,/g, (m) => m.replace(",", "."));
const textLines = lines.slice(i + 1);
out.push(time, ...textLines, "");
}
return out.join("\n");
}
// src/hooks/useSubtitles.ts
export function useSubtitles(subtitles?: SubtitleTrack[]) {
const [processed, setProcessed] = useState<SubtitleTrack[] | undefined>();
useEffect(() => {
let cancelled = false;
let cleanup: (() => void) | undefined;
(async () => {
const { processed, revoke } = await processSubtitles(subtitles);
if (!cancelled) setProcessed(processed);
cleanup = revoke;
})();
return () => {
cancelled = true;
cleanup?.();
};
}, [subtitles]);
return processed ?? subtitles;
}
.vtt during your build..srt files need permissive CORS (Access-Control-Allow-Origin). Local files under public/subs/ work out of the box..srt files and they’ll “just work” without extra build steps.processSubtitles creates Blob URLs for the converted VTT. The hook gives you a revoke cleanup so those URLs are released when the component unmounts or tracks change./subs/TOS-en.srt and enable the English track..srt is fetched once, then the player uses an in‑memory Blob URL for the VTT.
Persist and restore playback position, and reflect it in the catalog UI.
12 Sep 2025 - 22 days ago