diff --git a/web/src/components/player/LivePlayer.tsx b/web/src/components/player/LivePlayer.tsx index 6c223d651..ffa1579dc 100644 --- a/web/src/components/player/LivePlayer.tsx +++ b/web/src/components/player/LivePlayer.tsx @@ -138,6 +138,7 @@ export default function LivePlayer({ iOSCompatFullScreen={iOSCompatFullScreen} onPlaying={() => setLiveReady(true)} pip={pip} + onError={onError} /> ); } else if (liveMode == "mse") { diff --git a/web/src/components/player/MsePlayer.tsx b/web/src/components/player/MsePlayer.tsx index d240f0a83..cb0340ebc 100644 --- a/web/src/components/player/MsePlayer.tsx +++ b/web/src/components/player/MsePlayer.tsx @@ -8,6 +8,7 @@ import { useRef, useState, } from "react"; +import { isIOS, isSafari } from "react-device-detect"; type MSEPlayerProps = { camera: string; @@ -311,26 +312,27 @@ function MSEPlayer({ onPlaying?.(); }} muted={!audioEnabled} - onProgress={ - onError != undefined - ? () => { - if (videoRef.current?.paused) { - return; - } + onProgress={() => { + if (isSafari || isIOS) { + onPlaying?.(); + } + if (onError != undefined) { + if (videoRef.current?.paused) { + return; + } - if (bufferTimeout) { - clearTimeout(bufferTimeout); - setBufferTimeout(undefined); - } + if (bufferTimeout) { + clearTimeout(bufferTimeout); + setBufferTimeout(undefined); + } - setBufferTimeout( - setTimeout(() => { - onError("stalled"); - }, 3000), - ); - } - : undefined - } + setBufferTimeout( + setTimeout(() => { + onError("stalled"); + }, 3000), + ); + } + }} onError={(e) => { if ( // @ts-expect-error code does exist @@ -339,6 +341,16 @@ function MSEPlayer({ onError?.("startup"); } + if ( + // @ts-expect-error code does exist + e.target.error.code == MediaError.MEDIA_ERR_DECODE && + (isSafari || isIOS) + ) { + onError?.("mse-decode"); + clearTimeout(bufferTimeout); + setBufferTimeout(undefined); + } + if (wsRef.current) { wsRef.current.close(); wsRef.current = null; diff --git a/web/src/components/player/WebRTCPlayer.tsx b/web/src/components/player/WebRTCPlayer.tsx index 8f64e6cae..1e5e209d9 100644 --- a/web/src/components/player/WebRTCPlayer.tsx +++ b/web/src/components/player/WebRTCPlayer.tsx @@ -36,6 +36,7 @@ export default function WebRtcPlayer({ const pcRef = useRef(); const videoRef = useRef(null); const [bufferTimeout, setBufferTimeout] = useState(); + const videoLoadTimeoutRef = useRef(); const PeerConnection = useCallback( async (media: string) => { @@ -193,6 +194,27 @@ export default function WebRtcPlayer({ videoRef.current.requestPictureInPicture(); }, [pip, videoRef]); + useEffect(() => { + videoLoadTimeoutRef.current = setTimeout(() => { + onError?.("stalled"); + }, 5000); + + return () => { + if (videoLoadTimeoutRef.current) { + clearTimeout(videoLoadTimeoutRef.current); + } + }; + // we know that these deps are correct + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const handleLoadedData = () => { + if (videoLoadTimeoutRef.current) { + clearTimeout(videoLoadTimeoutRef.current); + } + onPlaying?.(); + }; + return (