From 9e00f4a7f5e01b5842bf635e34318dd0a231d3c1 Mon Sep 17 00:00:00 2001 From: Nick Mowen Date: Sun, 17 Dec 2023 14:15:53 -0700 Subject: [PATCH] Fix jsmpeg --- .../components/player/BirdseyeLivePlayer.tsx | 2 +- web/src/components/player/JSMpegPlayer.tsx | 64 +++++++++++++++---- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/web/src/components/player/BirdseyeLivePlayer.tsx b/web/src/components/player/BirdseyeLivePlayer.tsx index 4f50c3034..a43e2266a 100644 --- a/web/src/components/player/BirdseyeLivePlayer.tsx +++ b/web/src/components/player/BirdseyeLivePlayer.tsx @@ -1,5 +1,5 @@ import WebRtcPlayer from "./WebRTCPlayer"; -import { BirdseyeConfig, CameraConfig } from "@/types/frigateConfig"; +import { BirdseyeConfig } from "@/types/frigateConfig"; import ActivityIndicator from "../ui/activity-indicator"; import JSMpegPlayer from "./JSMpegPlayer"; diff --git a/web/src/components/player/JSMpegPlayer.tsx b/web/src/components/player/JSMpegPlayer.tsx index 90772960a..933342ce4 100644 --- a/web/src/components/player/JSMpegPlayer.tsx +++ b/web/src/components/player/JSMpegPlayer.tsx @@ -1,6 +1,8 @@ import { baseUrl } from "@/api/baseUrl"; +import { useResizeObserver } from "@/hooks/resize-observer"; +// @ts-ignore we know this doesn't have types import JSMpeg from "@cycjimmy/jsmpeg-player"; -import { useEffect, useRef } from "react"; +import { useEffect, useMemo, useRef } from "react"; type JSMpegPlayerProps = { camera: string; @@ -13,10 +15,43 @@ export default function JSMpegPlayer({ width, height, }: JSMpegPlayerProps) { - const playerRef = useRef(null); const url = `${baseUrl.replace(/^http/, "ws")}live/jsmpeg/${camera}`; + const playerRef = useRef(null); + const containerRef = useRef(null); + const [{ width: containerWidth }] = useResizeObserver(containerRef); + + // Add scrollbar width (when visible) to the available observer width to eliminate screen juddering. + // https://github.com/blakeblackshear/frigate/issues/1657 + let scrollBarWidth = 0; + if (window.innerWidth && document.body.offsetWidth) { + scrollBarWidth = window.innerWidth - document.body.offsetWidth; + } + const availableWidth = scrollBarWidth + ? containerWidth + scrollBarWidth + : containerWidth; + const aspectRatio = width / height; + + const scaledHeight = useMemo(() => { + const scaledHeight = Math.floor(availableWidth / aspectRatio); + const finalHeight = Math.min(scaledHeight, height); + + if (finalHeight > 0) { + return finalHeight; + } + + return 100; + }, [availableWidth, aspectRatio, height]); + const scaledWidth = useMemo( + () => Math.ceil(scaledHeight * aspectRatio - scrollBarWidth), + [scaledHeight, aspectRatio, scrollBarWidth] + ); useEffect(() => { + if (!playerRef.current) { + return; + } + + console.log("player ref exists and creating video"); const video = new JSMpeg.VideoElement( playerRef.current, url, @@ -35,18 +70,25 @@ export default function JSMpegPlayer({ video.els.canvas.addEventListener("click", fullscreen); return () => { - video.destroy(); + if (playerRef.current) { + try { + video.destroy(); + } catch (e) {} + playerRef.current = null; + } }; }, [url]); return ( -
+
+
+
); }