From 21780576339ecf20f0b1e53bf20605bfb20f146b Mon Sep 17 00:00:00 2001 From: frost768 Date: Thu, 6 Apr 2023 01:49:33 +0300 Subject: [PATCH] auto select subtitle --- src/backend/helpers/captions.ts | 4 ++ .../controllers/SourceController.tsx | 48 +++++++++++++++++-- .../popouts/CaptionSelectionPopout.tsx | 7 +-- .../popouts/CaptionSettingsPopout.tsx | 9 +--- src/views/developer/VideoTesterView.tsx | 1 + src/views/media/MediaView.tsx | 1 + 6 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/backend/helpers/captions.ts b/src/backend/helpers/captions.ts index 83edaa84..b5e40108 100644 --- a/src/backend/helpers/captions.ts +++ b/src/backend/helpers/captions.ts @@ -4,6 +4,10 @@ import DOMPurify from "dompurify"; import { parse, detect, list } from "subsrt-ts"; import { ContentCaption } from "subsrt-ts/dist/types/handler"; +export const customCaption = "external-custom"; +export function makeCaptionId(caption: MWCaption, isLinked: boolean): string { + return isLinked ? `linked-${caption.langIso}` : `external-${caption.langIso}`; +} export const subtitleTypeList = list().map((type) => `.${type}`); export const sanitize = DOMPurify.sanitize; export async function getCaptionUrl(caption: MWCaption): Promise { diff --git a/src/video/components/controllers/SourceController.tsx b/src/video/components/controllers/SourceController.tsx index 14d5ad93..fe98a685 100644 --- a/src/video/components/controllers/SourceController.tsx +++ b/src/video/components/controllers/SourceController.tsx @@ -1,4 +1,11 @@ -import { MWStreamQuality, MWStreamType } from "@/backend/helpers/streams"; +import { getCaptionUrl, makeCaptionId } from "@/backend/helpers/captions"; +import { + MWCaption, + MWStreamQuality, + MWStreamType, +} from "@/backend/helpers/streams"; +import { captionLanguages } from "@/setup/iso6391"; +import { useSettings } from "@/state/settings"; import { useInitialized } from "@/video/components/hooks/useInitialized"; import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useControls } from "@/video/state/logic/controls"; @@ -10,6 +17,19 @@ interface SourceControllerProps { quality: MWStreamQuality; providerId?: string; embedId?: string; + captions: MWCaption[]; +} +async function tryFetch(captions: MWCaption[]) { + for (let i = 0; i < captions.length; i += 1) { + const caption = captions[i]; + try { + const blobUrl = await getCaptionUrl(caption); + return { caption, blobUrl }; + } catch (error) { + continue; + } + } + return null; } export function SourceController(props: SourceControllerProps) { @@ -17,13 +37,35 @@ export function SourceController(props: SourceControllerProps) { const controls = useControls(descriptor); const { initialized } = useInitialized(descriptor); const didInitialize = useRef(false); - + const { captionSettings } = useSettings(); useEffect(() => { if (didInitialize.current) return; if (!initialized) return; controls.setSource(props); + // get preferred language + const preferredLanguage = captionLanguages.find( + (v) => v.id === captionSettings.language + ); + if (!preferredLanguage) return; + const captions = props.captions.filter( + (v) => + // langIso may contain the English name or the native name of the language + v.langIso.indexOf(preferredLanguage.englishName) !== -1 || + v.langIso.indexOf(preferredLanguage.nativeName) !== -1 + ); + if (!captions) return; + // caption url can return a response other than 200 + // that's why we fetch until we get a 200 response + tryFetch(captions).then((response) => { + // none of them were successful + if (!response) return; + // set the preferred language + const id = makeCaptionId(response.caption, true); + controls.setCaption(id, response.blobUrl); + }); + didInitialize.current = true; - }, [props, controls, initialized]); + }, [props, controls, initialized, captionSettings.language]); return null; } diff --git a/src/video/components/popouts/CaptionSelectionPopout.tsx b/src/video/components/popouts/CaptionSelectionPopout.tsx index 2ae9fced..3f595757 100644 --- a/src/video/components/popouts/CaptionSelectionPopout.tsx +++ b/src/video/components/popouts/CaptionSelectionPopout.tsx @@ -1,5 +1,7 @@ import { + customCaption, getCaptionUrl, + makeCaptionId, parseSubtitles, subtitleTypeList, } from "@/backend/helpers/captions"; @@ -17,11 +19,6 @@ import { useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { PopoutListEntry, PopoutSection } from "./PopoutUtils"; -const customCaption = "external-custom"; -function makeCaptionId(caption: MWCaption, isLinked: boolean): string { - return isLinked ? `linked-${caption.langIso}` : `external-${caption.langIso}`; -} - export function CaptionSelectionPopout(props: { router: ReturnType; prefix: string; diff --git a/src/video/components/popouts/CaptionSettingsPopout.tsx b/src/video/components/popouts/CaptionSettingsPopout.tsx index 09bf6eea..d4f212a5 100644 --- a/src/video/components/popouts/CaptionSettingsPopout.tsx +++ b/src/video/components/popouts/CaptionSettingsPopout.tsx @@ -106,14 +106,7 @@ export function CaptionSettingsPopout(props: { captionSettings.style.backgroundColor.substring(7, 9), 16 )} - onChange={(e) => - setCaptionBackgroundColor( - `${captionSettings.style.backgroundColor.substring( - 0, - 7 - )}${e.target.valueAsNumber.toString(16)}` - ) - } + onChange={(e) => setCaptionBackgroundColor(e.target.valueAsNumber)} />
diff --git a/src/views/media/MediaView.tsx b/src/views/media/MediaView.tsx index b674fb9f..c2ee94e7 100644 --- a/src/views/media/MediaView.tsx +++ b/src/views/media/MediaView.tsx @@ -148,6 +148,7 @@ export function MediaViewPlayer(props: MediaViewPlayerProps) { quality={props.stream.quality} embedId={props.stream.embedId} providerId={props.stream.providerId} + captions={props.stream.captions} />