mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-11 01:05:08 +01:00
track element support
This commit is contained in:
parent
454fa1279b
commit
596e97e1ba
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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}`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user