mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-13 14:45:25 +03:00
refactor camera live mode hook
This commit is contained in:
parent
b6b96dafa3
commit
398ad2e6cc
@ -1,49 +1,65 @@
|
|||||||
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig";
|
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { useMemo } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { usePersistence } from "./use-persistence";
|
|
||||||
import { LivePlayerMode } from "@/types/live";
|
import { LivePlayerMode } from "@/types/live";
|
||||||
|
|
||||||
export default function useCameraLiveMode(
|
export default function useCameraLiveMode(
|
||||||
cameraConfig: CameraConfig,
|
cameras: CameraConfig[],
|
||||||
preferredMode?: LivePlayerMode,
|
windowVisible: boolean,
|
||||||
): LivePlayerMode | undefined {
|
) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
const [preferredLiveModes, setPreferredLiveModes] = useState<{
|
||||||
|
[key: string]: LivePlayerMode;
|
||||||
|
}>({});
|
||||||
|
|
||||||
const restreamEnabled = useMemo(() => {
|
useEffect(() => {
|
||||||
if (!config) {
|
if (!cameras) return;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
const mseSupported =
|
||||||
cameraConfig &&
|
"MediaSource" in window || "ManagedMediaSource" in window;
|
||||||
Object.keys(config.go2rtc.streams || {}).includes(
|
|
||||||
cameraConfig.live.stream_name,
|
const newPreferredLiveModes = cameras.reduce(
|
||||||
)
|
(acc, camera) => {
|
||||||
|
const isRestreamed =
|
||||||
|
config &&
|
||||||
|
Object.keys(config.go2rtc.streams || {}).includes(
|
||||||
|
camera.live.stream_name,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mseSupported) {
|
||||||
|
acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg";
|
||||||
|
} else {
|
||||||
|
acc[camera.name] = isRestreamed ? "mse" : "jsmpeg";
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as { [key: string]: LivePlayerMode },
|
||||||
);
|
);
|
||||||
}, [config, cameraConfig]);
|
|
||||||
const defaultLiveMode = useMemo<LivePlayerMode | undefined>(() => {
|
|
||||||
if (config) {
|
|
||||||
if (restreamEnabled) {
|
|
||||||
return preferredMode || "mse";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "jsmpeg";
|
setPreferredLiveModes(newPreferredLiveModes);
|
||||||
}
|
}, [cameras, config, windowVisible]);
|
||||||
|
|
||||||
return undefined;
|
const resetPreferredLiveMode = useCallback(
|
||||||
}, [config, preferredMode, restreamEnabled]);
|
(cameraName: string) => {
|
||||||
const [viewSource] = usePersistence<LivePlayerMode>(
|
const mseSupported =
|
||||||
`${cameraConfig.name}-source`,
|
"MediaSource" in window || "ManagedMediaSource" in window;
|
||||||
defaultLiveMode,
|
const isRestreamed =
|
||||||
|
config && Object.keys(config.go2rtc.streams || {}).includes(cameraName);
|
||||||
|
|
||||||
|
setPreferredLiveModes((prevModes) => {
|
||||||
|
const newModes = { ...prevModes };
|
||||||
|
|
||||||
|
if (!mseSupported) {
|
||||||
|
newModes[cameraName] = isRestreamed ? "webrtc" : "jsmpeg";
|
||||||
|
} else {
|
||||||
|
newModes[cameraName] = isRestreamed ? "mse" : "jsmpeg";
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModes;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[config],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
return { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode };
|
||||||
restreamEnabled &&
|
|
||||||
(preferredMode == "mse" || preferredMode == "webrtc")
|
|
||||||
) {
|
|
||||||
return preferredMode;
|
|
||||||
} else {
|
|
||||||
return viewSource;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
import useCameraLiveMode from "@/hooks/use-camera-live-mode";
|
||||||
|
|
||||||
type DraggableGridLayoutProps = {
|
type DraggableGridLayoutProps = {
|
||||||
cameras: CameraConfig[];
|
cameras: CameraConfig[];
|
||||||
@ -55,7 +56,6 @@ type DraggableGridLayoutProps = {
|
|||||||
setIsEditMode: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsEditMode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
fullscreen: boolean;
|
fullscreen: boolean;
|
||||||
toggleFullscreen: () => void;
|
toggleFullscreen: () => void;
|
||||||
resetPreferredLiveMode: (camera: string) => void;
|
|
||||||
};
|
};
|
||||||
export default function DraggableGridLayout({
|
export default function DraggableGridLayout({
|
||||||
cameras,
|
cameras,
|
||||||
@ -70,43 +70,14 @@ export default function DraggableGridLayout({
|
|||||||
setIsEditMode,
|
setIsEditMode,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
toggleFullscreen,
|
toggleFullscreen,
|
||||||
resetPreferredLiveMode,
|
|
||||||
}: DraggableGridLayoutProps) {
|
}: DraggableGridLayoutProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const birdseyeConfig = useMemo(() => config?.birdseye, [config]);
|
const birdseyeConfig = useMemo(() => config?.birdseye, [config]);
|
||||||
|
|
||||||
// preferred live modes per camera
|
// preferred live modes per camera
|
||||||
|
|
||||||
const [preferredLiveModes, setPreferredLiveModes] = useState<{
|
const { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode } =
|
||||||
[key: string]: LivePlayerMode;
|
useCameraLiveMode(cameras, windowVisible);
|
||||||
}>({});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!cameras) return;
|
|
||||||
|
|
||||||
const mseSupported =
|
|
||||||
"MediaSource" in window || "ManagedMediaSource" in window;
|
|
||||||
|
|
||||||
const newPreferredLiveModes = cameras.reduce(
|
|
||||||
(acc, camera) => {
|
|
||||||
const isRestreamed =
|
|
||||||
config &&
|
|
||||||
Object.keys(config.go2rtc.streams || {}).includes(
|
|
||||||
camera.live.stream_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!mseSupported) {
|
|
||||||
acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg";
|
|
||||||
} else {
|
|
||||||
acc[camera.name] = isRestreamed ? "mse" : "jsmpeg";
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as { [key: string]: LivePlayerMode },
|
|
||||||
);
|
|
||||||
|
|
||||||
setPreferredLiveModes(newPreferredLiveModes);
|
|
||||||
}, [cameras, config, windowVisible]);
|
|
||||||
|
|
||||||
const ResponsiveGridLayout = useMemo(() => WidthProvider(Responsive), []);
|
const ResponsiveGridLayout = useMemo(() => WidthProvider(Responsive), []);
|
||||||
|
|
||||||
|
|||||||
@ -28,10 +28,11 @@ import DraggableGridLayout from "./DraggableGridLayout";
|
|||||||
import { IoClose } from "react-icons/io5";
|
import { IoClose } from "react-icons/io5";
|
||||||
import { LuLayoutDashboard } from "react-icons/lu";
|
import { LuLayoutDashboard } from "react-icons/lu";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { LivePlayerError, LivePlayerMode } from "@/types/live";
|
import { LivePlayerError } from "@/types/live";
|
||||||
import { FaCompress, FaExpand } from "react-icons/fa";
|
import { FaCompress, FaExpand } from "react-icons/fa";
|
||||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||||
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
||||||
|
import useCameraLiveMode from "@/hooks/use-camera-live-mode";
|
||||||
|
|
||||||
type LiveDashboardViewProps = {
|
type LiveDashboardViewProps = {
|
||||||
cameras: CameraConfig[];
|
cameras: CameraConfig[];
|
||||||
@ -130,9 +131,6 @@ export default function LiveDashboardView({
|
|||||||
// camera live views
|
// camera live views
|
||||||
|
|
||||||
const [autoLiveView] = usePersistence("autoLiveView", true);
|
const [autoLiveView] = usePersistence("autoLiveView", true);
|
||||||
const [preferredLiveModes, setPreferredLiveModes] = useState<{
|
|
||||||
[key: string]: LivePlayerMode;
|
|
||||||
}>({});
|
|
||||||
|
|
||||||
const [{ height: containerHeight }] = useResizeObserver(containerRef);
|
const [{ height: containerHeight }] = useResizeObserver(containerRef);
|
||||||
|
|
||||||
@ -187,54 +185,8 @@ export default function LiveDashboardView({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
const { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode } =
|
||||||
if (!cameras) return;
|
useCameraLiveMode(cameras, windowVisible);
|
||||||
|
|
||||||
const mseSupported =
|
|
||||||
"MediaSource" in window || "ManagedMediaSource" in window;
|
|
||||||
|
|
||||||
const newPreferredLiveModes = cameras.reduce(
|
|
||||||
(acc, camera) => {
|
|
||||||
const isRestreamed =
|
|
||||||
config &&
|
|
||||||
Object.keys(config.go2rtc.streams || {}).includes(
|
|
||||||
camera.live.stream_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!mseSupported) {
|
|
||||||
acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg";
|
|
||||||
} else {
|
|
||||||
acc[camera.name] = isRestreamed ? "mse" : "jsmpeg";
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as { [key: string]: LivePlayerMode },
|
|
||||||
);
|
|
||||||
|
|
||||||
setPreferredLiveModes(newPreferredLiveModes);
|
|
||||||
}, [cameras, config, windowVisible]);
|
|
||||||
|
|
||||||
const resetPreferredLiveMode = useCallback(
|
|
||||||
(cameraName: string) => {
|
|
||||||
const mseSupported =
|
|
||||||
"MediaSource" in window || "ManagedMediaSource" in window;
|
|
||||||
const isRestreamed =
|
|
||||||
config && Object.keys(config.go2rtc.streams || {}).includes(cameraName);
|
|
||||||
|
|
||||||
setPreferredLiveModes((prevModes) => {
|
|
||||||
const newModes = { ...prevModes };
|
|
||||||
|
|
||||||
if (!mseSupported) {
|
|
||||||
newModes[cameraName] = isRestreamed ? "webrtc" : "jsmpeg";
|
|
||||||
} else {
|
|
||||||
newModes[cameraName] = isRestreamed ? "mse" : "jsmpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModes;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[config],
|
|
||||||
);
|
|
||||||
|
|
||||||
const cameraRef = useCallback(
|
const cameraRef = useCallback(
|
||||||
(node: HTMLElement | null) => {
|
(node: HTMLElement | null) => {
|
||||||
@ -465,7 +417,6 @@ export default function LiveDashboardView({
|
|||||||
setIsEditMode={setIsEditMode}
|
setIsEditMode={setIsEditMode}
|
||||||
fullscreen={fullscreen}
|
fullscreen={fullscreen}
|
||||||
toggleFullscreen={toggleFullscreen}
|
toggleFullscreen={toggleFullscreen}
|
||||||
resetPreferredLiveMode={resetPreferredLiveMode}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user