wip: CanPlay check

This commit is contained in:
Zoe Roux 2024-05-12 02:54:42 +02:00
parent 55f55db030
commit 69a2821477
No known key found for this signature in database
6 changed files with 46 additions and 10 deletions

View File

@ -149,6 +149,11 @@ export const WatchInfoP = z
* The extension used to store this video file.
*/
extension: z.string(),
/**
* The whole mimetype (defined as the RFC 6381).
* ex: `video/mp4; codecs="avc1.640028, mp4a.40.2"`
*/
mimeCodec: z.string(),
/**
* The file size of the video file.
*/

View File

@ -153,6 +153,7 @@ export const Player = ({
links={data?.links}
audios={info?.audios}
subtitles={info?.subtitles}
codec={info?.mimeCodec}
setError={setPlaybackError}
fonts={info?.fonts}
startTime={startTime}

View File

@ -100,6 +100,7 @@ export const Video = memo(function Video({
links,
subtitles,
audios,
codec,
setError,
fonts,
startTime: startTimeP,
@ -108,6 +109,7 @@ export const Video = memo(function Video({
links?: Episode["links"];
subtitles?: Subtitle[];
audios?: Audio[];
codec?: string;
setError: (error: string | undefined) => void;
fonts?: string[];
startTime?: number | null;
@ -133,9 +135,19 @@ export const Video = memo(function Video({
const getProgress = useAtomCallback(useCallback((get) => get(progressAtom), []));
const oldLinks = useRef<typeof links | null>(null);
useLayoutEffect(() => {
useEffect(() => {
// Reset the state when a new video is loaded.
setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
let newMode = getLocalSetting("playmode", "direct") !== "auto" ? PlayMode.Direct : PlayMode.Hls;
// Only allow direct play if the device supports it
console.log(codec, ref.current, ref.current?.canPlay?.(codec!))
if (newMode === PlayMode.Direct && codec && ref.current?.canPlay?.(codec) === false) {
console.log(`Browser can't natively play ${codec}, switching to hls stream.`);
newMode = PlayMode.Hls;
}
setPlayMode(newMode);
setSource((newMode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
setLoad(true);
if (oldLinks.current !== links) {
setPrivateProgress(startTime.current ?? 0);
@ -146,7 +158,16 @@ export const Video = memo(function Video({
}
oldLinks.current = links;
setPlay(true);
}, [mode, links, setLoad, setPrivateProgress, setPublicProgress, setPlay, getProgress]);
}, [
links,
codec,
setLoad,
setPrivateProgress,
setPublicProgress,
setPlay,
getProgress,
setPlayMode,
]);
const account = useAccount();
const defaultSubLanguage = account?.settings.subtitleLanguage;

View File

@ -29,6 +29,10 @@ declare module "react-native-video" {
export type VideoProps = Omit<ReactVideoProps, "source"> & {
source: { uri: string; hls: string | null; startPosition?: number };
};
interface VideoRef {
canPlay?: (codec: string) => boolean;
}
}
export * from "react-native-video";

View File

@ -104,7 +104,10 @@ const initHls = (): Hls => {
return hls;
};
const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function Video(
const Video = forwardRef<
{ seek: (value: number) => void; canPlay: (codec: string) => boolean },
VideoProps
>(function Video(
{
source,
paused,
@ -124,6 +127,8 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
const ref = useRef<HTMLVideoElement>(null);
const oldHls = useRef<string | null>(null);
const { css } = useYoshiki();
const errorHandler = useRef<typeof onError>(onError);
errorHandler.current = onError;
useImperativeHandle(
forwaredRef,
@ -131,6 +136,10 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
seek: (value: number) => {
if (ref.current) ref.current.currentTime = value;
},
canPlay: (codec: string) => {
if (!ref.current) return false;
return !!ref.current.canPlayType(codec);
},
}),
[],
);
@ -148,7 +157,6 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
const subtitle = useAtomValue(subtitleAtom);
useSubtitle(ref, subtitle, fonts);
// biome-ignore lint/correctness/useExhaustiveDependencies: onError changes should not restart the playback.
useLayoutEffect(() => {
if (!ref?.current || !source.uri) return;
if (!hls || oldHls.current !== source.hls) {
@ -168,7 +176,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
hls.on(Hls.Events.ERROR, (_, d) => {
if (!d.fatal || !hls?.media) return;
console.warn("Hls error", d);
onError?.call(null, {
errorHandler.current?.({
error: { errorString: d.reason ?? d.error?.message ?? "Unknown hls error" },
});
});

View File

@ -55,10 +55,7 @@ export const PlaybackSettings = () => {
<Select
label={t("settings.playback.playmode.label")}
value={playMode}
onValueChange={(value) => {
setDefaultPlayMode(value);
setCurrentPlayMode(value === "direct" ? PlayMode.Direct : PlayMode.Hls);
}}
onValueChange={(value) => setDefaultPlayMode(value)}
values={["direct", "auto"]}
getLabel={(key) => t(`player.${key}`)}
/>