mirror of
https://github.com/movie-web/movie-web.git
synced 2025-01-04 05:55:59 +00:00
auto select subtitle
This commit is contained in:
parent
9e961223f6
commit
2178057633
|
@ -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<string> {
|
||||
|
|
|
@ -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<boolean>(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;
|
||||
}
|
||||
|
|
|
@ -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<typeof useFloatingRouter>;
|
||||
prefix: string;
|
||||
|
|
|
@ -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)}
|
||||
/>
|
||||
<div className="flex flex-row justify-between">
|
||||
<label className="font-bold" htmlFor="color">
|
||||
|
|
|
@ -66,6 +66,7 @@ export default function VideoTesterView() {
|
|||
source={video.streamUrl}
|
||||
type={videoType}
|
||||
quality={MWStreamQuality.QUNKNOWN}
|
||||
captions={[]}
|
||||
/>
|
||||
</VideoPlayer>
|
||||
</div>
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
<ProgressListenerController
|
||||
startAt={firstStartTime.current}
|
||||
|
|
Loading…
Reference in a new issue