Fix live hls issues

This commit is contained in:
Zoe Roux 2023-06-02 18:25:51 +09:00
parent 6f4936f6be
commit f49882fb0d
2 changed files with 26 additions and 7 deletions

View File

@ -88,6 +88,7 @@ export const Video = memo(function _Video({
const publicProgress = useAtomValue(publicProgressAtom); const publicProgress = useAtomValue(publicProgressAtom);
const setPrivateProgress = useSetAtom(privateProgressAtom); const setPrivateProgress = useSetAtom(privateProgressAtom);
const setPublicProgress = useSetAtom(publicProgressAtom);
const setBuffered = useSetAtom(bufferedAtom); const setBuffered = useSetAtom(bufferedAtom);
const setDuration = useSetAtom(durationAtom); const setDuration = useSetAtom(durationAtom);
useEffect(() => { useEffect(() => {
@ -99,8 +100,9 @@ export const Video = memo(function _Video({
setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null); setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
setLoad(true); setLoad(true);
setPrivateProgress(0); setPrivateProgress(0);
setPublicProgress(0);
setPlay(true); setPlay(true);
}, [mode, links, setLoad, setPrivateProgress, setPlay]); }, [mode, links, setLoad, setPrivateProgress, setPublicProgress, setPlay]);
const volume = useAtomValue(volumeAtom); const volume = useAtomValue(volumeAtom);
const isMuted = useAtomValue(mutedAtom); const isMuted = useAtomValue(mutedAtom);

View File

@ -38,7 +38,7 @@ import Hls, { Level } from "hls.js";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Menu } from "@kyoo/primitives"; import { Menu } from "@kyoo/primitives";
let hls: Hls = null!; let hls: Hls | null = null;
function uuidv4(): string { function uuidv4(): string {
// @ts-ignore I have no clue how this works, thanks https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid // @ts-ignore I have no clue how this works, thanks https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
@ -49,16 +49,20 @@ function uuidv4(): string {
let client_id = typeof window === "undefined" ? "ssr" : uuidv4(); let client_id = typeof window === "undefined" ? "ssr" : uuidv4();
const initHls = async () => { const initHls = async (): Promise<Hls> => {
if (hls !== null) return; if (hls !== null) return hls;
const token = await getToken(); const token = await getToken();
hls = new Hls({ hls = new Hls({
xhrSetup: (xhr) => { xhrSetup: (xhr) => {
if (token) xhr.setRequestHeader("Authorization", `Bearer: {token}`); if (token) xhr.setRequestHeader("Authorization", `Bearer: {token}`);
xhr.setRequestHeader("X-CLIENT-ID", client_id); xhr.setRequestHeader("X-CLIENT-ID", client_id);
}, },
autoStartLoad: false,
// debug: true,
startPosition: 0,
}); });
// hls.currentLevel = hls.startLevel; // hls.currentLevel = hls.startLevel;
return hls;
}; };
const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function _Video( const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function _Video(
@ -109,8 +113,12 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
useLayoutEffect(() => { useLayoutEffect(() => {
(async () => { (async () => {
if (!ref?.current || !source.uri) return; if (!ref?.current || !source.uri) return;
await initHls(); if (!hls || oldHls.current !== source.hls) {
if (oldHls.current !== source.hls) { // Reinit the hls player when we change track.
if (hls)
hls.destroy();
hls = null;
hls = await initHls();
// Still load the hls source to list available qualities. // Still load the hls source to list available qualities.
// Note: This may ask the server to transmux the audio/video by loading the index.m3u8 // Note: This may ask the server to transmux the audio/video by loading the index.m3u8
hls.loadSource(source.hls); hls.loadSource(source.hls);
@ -121,14 +129,23 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
ref.current.src = source.uri; ref.current.src = source.uri;
} else { } else {
hls.attachMedia(ref.current); hls.attachMedia(ref.current);
// TODO: Enable custom XHR for tokens hls.startLoad(0);
hls.on(Hls.Events.MANIFEST_LOADED, async () => { hls.on(Hls.Events.MANIFEST_LOADED, async () => {
try { try {
await ref.current?.play(); await ref.current?.play();
} catch { } } catch { }
}); });
hls.on(Hls.Events.ERROR, (_, d) => {
console.log("Hls error", d);
if (!d.fatal) return;
onError?.call(null, {
error: { "": "", errorString: d.reason ?? d.err?.message ?? "Unknown hls error" },
});
});
} }
})(); })();
// onError changes should not restart the playback.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [source.uri, source.hls]); }, [source.uri, source.hls]);
const setPlay = useSetAtom(playAtom); const setPlay = useSetAtom(playAtom);