track element support

This commit is contained in:
mrjvs 2023-10-18 15:00:12 +02:00
parent 454fa1279b
commit 596e97e1ba
2 changed files with 40 additions and 3 deletions

View File

@ -1,6 +1,10 @@
import { useEffect, useRef } from "react";
import { ReactNode, useEffect, useMemo, useRef } from "react";
import { makeVideoElementDisplayInterface } from "@/components/player/display/base";
import {
convertSubtitlesToVtt,
vttToDataurl,
} from "@/components/player/utils/captions";
import { playerStatus } from "@/stores/player/slices/source";
import { usePlayerStore } from "@/stores/player/store";
@ -39,6 +43,14 @@ export function useShouldShowVideoElement() {
function VideoElement() {
const videoEl = useRef<HTMLVideoElement>(null);
const display = usePlayerStore((s) => s.display);
const srtData = usePlayerStore((s) => s.caption.selected?.srtData);
const captionAsTrack = usePlayerStore((s) => s.caption.asTrack);
const language = usePlayerStore((s) => s.caption.selected?.language);
const trackData = useMemo(
() => (srtData ? vttToDataurl(convertSubtitlesToVtt(srtData)) : null),
[srtData]
);
// report video element to display interface
useEffect(() => {
@ -47,13 +59,27 @@ function VideoElement() {
}
}, [display, videoEl]);
let subtitleTrack: ReactNode = null;
if (captionAsTrack && trackData && language)
subtitleTrack = (
<track
label="Subtitles"
kind="subtitles"
srcLang={language}
src={trackData}
default
/>
);
return (
<video
className="absolute inset-0 w-full h-screen bg-black"
autoPlay
playsInline
ref={videoEl}
/>
>
{subtitleTrack}
</video>
);
}

View File

@ -23,7 +23,7 @@ export function makeQueId(index: number, start: number, end: number): string {
return `${index}-${start}-${end}`;
}
export function parseSubtitles(text: string): CaptionCueType[] {
export function convertSubtitlesToVtt(text: string): string {
const textTrimmed = text.trim();
if (textTrimmed === "") {
throw new Error("Given text is empty");
@ -32,5 +32,16 @@ export function parseSubtitles(text: string): CaptionCueType[] {
if (detect(vtt) === "") {
throw new Error("Invalid subtitle format");
}
return vtt;
}
export function parseSubtitles(text: string): CaptionCueType[] {
const vtt = convertSubtitlesToVtt(text);
return parse(vtt).filter((cue) => cue.type === "caption") as CaptionCueType[];
}
export function vttToDataurl(vtt: string): string {
const bytes = new TextEncoder().encode(vtt);
const encoded = btoa(String.fromCodePoint(...bytes));
return `data:text/vtt;base64,${encoded}`;
}