diff --git a/web/src/components/player/JSMpegPlayer.tsx b/web/src/components/player/JSMpegPlayer.tsx index cf25c54c6..91cd3e1c9 100644 --- a/web/src/components/player/JSMpegPlayer.tsx +++ b/web/src/components/player/JSMpegPlayer.tsx @@ -10,6 +10,7 @@ type JSMpegPlayerProps = { width: number; height: number; containerRef?: React.MutableRefObject; + onPlaying?: () => void; }; export default function JSMpegPlayer({ @@ -18,6 +19,7 @@ export default function JSMpegPlayer({ height, className, containerRef, + onPlaying, }: JSMpegPlayerProps) { const url = `${baseUrl.replace(/^http/, "ws")}live/jsmpeg/${camera}`; const playerRef = useRef(null); @@ -88,7 +90,14 @@ export default function JSMpegPlayer({ playerRef.current, url, { canvas: `#${CSS.escape(uniqueId)}` }, - { protocols: [], audio: false, videoBufferSize: 1024 * 1024 * 4 }, + { + protocols: [], + audio: false, + videoBufferSize: 1024 * 1024 * 4, + onPlay: () => { + onPlaying?.(); + }, + }, ); return () => { @@ -100,7 +109,7 @@ export default function JSMpegPlayer({ playerRef.current = null; } }; - }, [url, uniqueId]); + }, [url, uniqueId, onPlaying]); return (
diff --git a/web/src/components/player/LivePlayer.tsx b/web/src/components/player/LivePlayer.tsx index ffa1579dc..ae2940c36 100644 --- a/web/src/components/player/LivePlayer.tsx +++ b/web/src/components/player/LivePlayer.tsx @@ -172,6 +172,7 @@ export default function LivePlayer({ width={cameraConfig.detect.width} height={cameraConfig.detect.height} containerRef={containerRef} + onPlaying={() => setLiveReady(true)} /> ); } else { @@ -187,7 +188,8 @@ export default function LivePlayer({ data-camera={cameraConfig.name} className={cn( "relative flex w-full cursor-pointer justify-center outline", - activeTracking + activeTracking && + ((showStillWithoutActivity && !liveReady) || liveReady) ? "outline-3 rounded-lg shadow-severity_alert outline-severity_alert md:rounded-2xl" : "outline-0 outline-background", "transition-all duration-500", @@ -195,52 +197,60 @@ export default function LivePlayer({ )} onClick={onClick} > -
-
- {player} - - {objects.length > 0 && ( -
- -
- -
- - {[ - ...new Set([ - ...(objects || []).map(({ label }) => label), - ]), - ] - .map((label) => { - return getIconForLabel(label, "size-3 text-white"); - }) - .sort()} - -
-
-
- - {[ - ...new Set([ - ...(objects || []).map(({ label, sub_label }) => - label.endsWith("verified") ? sub_label : label, - ), - ]), - ] - .filter( - (label) => - label !== undefined && !label.includes("-verified"), - ) - .map((label) => capitalizeFirstLetter(label)) - .sort() - .join(", ") - .replaceAll("-verified", "")} - -
-
+ {((showStillWithoutActivity && !liveReady) || liveReady) && ( + <> +
+
+ )} + {player} + {!offline && !showStillWithoutActivity && !liveReady && ( + + )} + + {((showStillWithoutActivity && !liveReady) || liveReady) && + objects.length > 0 && ( +
+ +
+ +
+ + {[ + ...new Set([ + ...(objects || []).map(({ label }) => label), + ]), + ] + .map((label) => { + return getIconForLabel(label, "size-3 text-white"); + }) + .sort()} + +
+
+
+ + {[ + ...new Set([ + ...(objects || []).map(({ label, sub_label }) => + label.endsWith("verified") ? sub_label : label, + ), + ]), + ] + .filter( + (label) => + label !== undefined && !label.includes("-verified"), + ) + .map((label) => capitalizeFirstLetter(label)) + .sort() + .join(", ") + .replaceAll("-verified", "")} + +
+
+ )}
- {autoLive && !offline && activeMotion && ( - - )} + {autoLive && + !offline && + activeMotion && + ((showStillWithoutActivity && !liveReady) || liveReady) && ( + + )} {offline && ( { - onError("stalled"); + if (document.visibilityState === "visible") { + onError("stalled"); + } }, 3000), ); } diff --git a/web/src/components/player/WebRTCPlayer.tsx b/web/src/components/player/WebRTCPlayer.tsx index 1e5e209d9..3baf26d19 100644 --- a/web/src/components/player/WebRTCPlayer.tsx +++ b/web/src/components/player/WebRTCPlayer.tsx @@ -238,7 +238,9 @@ export default function WebRtcPlayer({ setBufferTimeout( setTimeout(() => { - onError("stalled"); + if (document.visibilityState === "visible") { + onError("stalled"); + } }, 3000), ); }