From 4165639308763154deb2526657eb865a68cc8e5a Mon Sep 17 00:00:00 2001
From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
Date: Tue, 28 May 2024 08:11:35 -0500
Subject: [PATCH] Live view tweaks and jsmpeg bugfix (#11584)
* live view tweaks and jsmpeg bugfix
* use container aspect in check
---
web/src/components/player/JSMpegPlayer.tsx | 6 +-
web/src/views/live/LiveBirdseyeView.tsx | 44 ++++-----
web/src/views/live/LiveCameraView.tsx | 102 ++++++++++-----------
3 files changed, 65 insertions(+), 87 deletions(-)
diff --git a/web/src/components/player/JSMpegPlayer.tsx b/web/src/components/player/JSMpegPlayer.tsx
index 2900defcf..62d794306 100644
--- a/web/src/components/player/JSMpegPlayer.tsx
+++ b/web/src/components/player/JSMpegPlayer.tsx
@@ -77,7 +77,7 @@ export default function JSMpegPlayer({
const video = new JSMpeg.VideoElement(
playerRef.current,
url,
- { canvas: "#video-canvas" },
+ { canvas: `#${camera}-canvas` },
{ protocols: [], audio: false, videoBufferSize: 1024 * 1024 * 4 },
);
@@ -90,13 +90,13 @@ export default function JSMpegPlayer({
playerRef.current = null;
}
};
- }, [url]);
+ }, [url, camera]);
return (
diff --git a/web/src/views/live/LiveCameraView.tsx b/web/src/views/live/LiveCameraView.tsx
index 096f0f6f6..e36375798 100644
--- a/web/src/views/live/LiveCameraView.tsx
+++ b/web/src/views/live/LiveCameraView.tsx
@@ -73,6 +73,7 @@ import {
import { useNavigate } from "react-router-dom";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import useSWR from "swr";
+import { useFullscreen } from "@/hooks/use-fullscreen";
type LiveCameraViewProps = {
config?: FrigateConfig;
@@ -177,19 +178,7 @@ export default function LiveCameraView({
// fullscreen / pip state
- useEffect(() => {
- if (mainRef.current == null) {
- return;
- }
- const fsListener = () => {
- setFullscreen(document.fullscreenElement != null);
- };
- document.addEventListener("fullscreenchange", fsListener);
-
- return () => {
- document.removeEventListener("fullscreenchange", fsListener);
- };
- }, [mainRef]);
+ const { fullscreen, toggleFullscreen } = useFullscreen(mainRef);
useEffect(() => {
setPip(document.pictureInPictureElement != null);
@@ -201,7 +190,6 @@ export default function LiveCameraView({
const [audio, setAudio] = useState(false);
const [mic, setMic] = useState(false);
- const [fullscreen, setFullscreen] = useState(false);
const [pip, setPip] = useState(false);
const [fullResolution, setFullResolution] = useState
({
@@ -209,37 +197,6 @@ export default function LiveCameraView({
height: 0,
});
- const growClassName = useMemo(() => {
- let aspect;
- if (fullResolution.width && fullResolution.height) {
- aspect = fullResolution.width / fullResolution.height;
- } else {
- aspect = camera.detect.width / camera.detect.height;
- }
-
- if (isMobile) {
- if (isPortrait) {
- return "absolute left-2 right-2 top-[50%] -translate-y-[50%]";
- } else {
- if (aspect > 1.5) {
- return "p-2 absolute left-0 top-[50%] -translate-y-[50%]";
- } else {
- return "p-2 absolute top-2 bottom-2 left-[50%] -translate-x-[50%]";
- }
- }
- }
-
- if (fullscreen) {
- if (aspect > 1.5) {
- return "absolute inset-x-2 top-[50%] -translate-y-[50%]";
- } else {
- return "absolute inset-y-2 left-[50%] -translate-x-[50%]";
- }
- } else {
- return "absolute top-2 bottom-2 left-[50%] -translate-x-[50%]";
- }
- }, [camera, fullscreen, isPortrait, fullResolution]);
-
const preferredLiveMode = useMemo(() => {
if (isSafari || mic) {
return "webrtc";
@@ -252,6 +209,14 @@ export default function LiveCameraView({
return windowWidth / windowHeight;
}, [windowWidth, windowHeight]);
+ const containerAspectRatio = useMemo(() => {
+ if (!containerRef.current) {
+ return windowAspectRatio;
+ }
+
+ return containerRef.current.clientWidth / containerRef.current.clientHeight;
+ }, [windowAspectRatio, containerRef]);
+
const cameraAspectRatio = useMemo(() => {
if (fullResolution.width && fullResolution.height) {
return fullResolution.width / fullResolution.height;
@@ -264,11 +229,42 @@ export default function LiveCameraView({
if (isMobile || fullscreen) {
return cameraAspectRatio;
} else {
- return windowAspectRatio < cameraAspectRatio
- ? windowAspectRatio - 0.05
- : cameraAspectRatio - 0.03;
+ return containerAspectRatio < cameraAspectRatio
+ ? containerAspectRatio
+ : cameraAspectRatio;
}
- }, [cameraAspectRatio, windowAspectRatio, fullscreen]);
+ }, [cameraAspectRatio, containerAspectRatio, fullscreen]);
+
+ const growClassName = useMemo(() => {
+ let aspect;
+ if (fullResolution.width && fullResolution.height) {
+ aspect = fullResolution.width / fullResolution.height;
+ } else {
+ aspect = camera.detect.width / camera.detect.height;
+ }
+
+ if (isMobile) {
+ if (isPortrait) {
+ return "absolute left-0.5 right-0.5 top-[50%] -translate-y-[50%]";
+ } else {
+ if (aspect > containerAspectRatio) {
+ return "p-2 absolute left-0 top-[50%] -translate-y-[50%]";
+ } else {
+ return "p-2 absolute top-0.5 bottom-0.5 left-[50%] -translate-x-[50%]";
+ }
+ }
+ }
+
+ if (fullscreen) {
+ if (aspect > containerAspectRatio) {
+ return "absolute inset-x-2 top-[50%] -translate-y-[50%]";
+ } else {
+ return "absolute inset-y-2 left-[50%] -translate-x-[50%]";
+ }
+ } else {
+ return "absolute top-0.5 bottom-0.5 left-[50%] -translate-x-[50%]";
+ }
+ }, [camera, fullscreen, isPortrait, fullResolution, containerAspectRatio]);
return (
@@ -333,13 +329,7 @@ export default function LiveCameraView({
Icon={fullscreen ? FaCompress : FaExpand}
isActive={fullscreen}
title={fullscreen ? "Close" : "Fullscreen"}
- onClick={() => {
- if (fullscreen) {
- document.exitFullscreen();
- } else {
- mainRef.current?.requestFullscreen();
- }
- }}
+ onClick={toggleFullscreen}
/>
)}
{!isIOS && (