mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-07 02:18:07 +01:00
Dynamically enable/disable cameras (#16894)
* config options * metrics * stop and restart ffmpeg processes * dispatcher * frontend websocket * buttons for testing * don't recreate log pipe * add/remove cam from birdseye when enabling/disabling * end all objects and send empty camera activity * enable/disable switch in ui * disable buttons when camera is disabled * use enabled_in_config for some frontend checks * tweaks * handle settings pane with disabled cameras * frontend tweaks * change to debug log * mqtt docs * tweak * ensure all ffmpeg processes are initially started * clean up * use zmq * remove camera metrics * remove camera metrics * tweaks * frontend tweaks
This commit is contained in:
@@ -22,6 +22,7 @@ import { TbExclamationCircle } from "react-icons/tb";
|
||||
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
||||
import { baseUrl } from "@/api/baseUrl";
|
||||
import { PlayerStats } from "./PlayerStats";
|
||||
import { LuVideoOff } from "react-icons/lu";
|
||||
|
||||
type LivePlayerProps = {
|
||||
cameraRef?: (ref: HTMLDivElement | null) => void;
|
||||
@@ -86,8 +87,13 @@ export default function LivePlayer({
|
||||
|
||||
// camera activity
|
||||
|
||||
const { activeMotion, activeTracking, objects, offline } =
|
||||
useCameraActivity(cameraConfig);
|
||||
const {
|
||||
enabled: cameraEnabled,
|
||||
activeMotion,
|
||||
activeTracking,
|
||||
objects,
|
||||
offline,
|
||||
} = useCameraActivity(cameraConfig);
|
||||
|
||||
const cameraActive = useMemo(
|
||||
() =>
|
||||
@@ -191,12 +197,37 @@ export default function LivePlayer({
|
||||
setLiveReady(true);
|
||||
}, []);
|
||||
|
||||
// enabled states
|
||||
|
||||
const [isReEnabling, setIsReEnabling] = useState(false);
|
||||
const prevCameraEnabledRef = useRef(cameraEnabled);
|
||||
|
||||
useEffect(() => {
|
||||
if (!prevCameraEnabledRef.current && cameraEnabled) {
|
||||
// Camera enabled
|
||||
setLiveReady(false);
|
||||
setIsReEnabling(true);
|
||||
setKey((prevKey) => prevKey + 1);
|
||||
} else if (prevCameraEnabledRef.current && !cameraEnabled) {
|
||||
// Camera disabled
|
||||
setLiveReady(false);
|
||||
setKey((prevKey) => prevKey + 1);
|
||||
}
|
||||
prevCameraEnabledRef.current = cameraEnabled;
|
||||
}, [cameraEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (liveReady && isReEnabling) {
|
||||
setIsReEnabling(false);
|
||||
}
|
||||
}, [liveReady, isReEnabling]);
|
||||
|
||||
if (!cameraConfig) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
|
||||
let player;
|
||||
if (!autoLive || !streamName) {
|
||||
if (!autoLive || !streamName || !cameraEnabled) {
|
||||
player = null;
|
||||
} else if (preferredLiveMode == "webrtc") {
|
||||
player = (
|
||||
@@ -267,6 +298,22 @@ export default function LivePlayer({
|
||||
player = <ActivityIndicator />;
|
||||
}
|
||||
|
||||
// if (cameraConfig.name == "lpr")
|
||||
// console.log(
|
||||
// cameraConfig.name,
|
||||
// "enabled",
|
||||
// cameraEnabled,
|
||||
// "prev enabled",
|
||||
// prevCameraEnabledRef.current,
|
||||
// "offline",
|
||||
// offline,
|
||||
// "show still",
|
||||
// showStillWithoutActivity,
|
||||
// "live ready",
|
||||
// liveReady,
|
||||
// player,
|
||||
// );
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={cameraRef ?? internalContainerRef}
|
||||
@@ -287,16 +334,18 @@ export default function LivePlayer({
|
||||
}
|
||||
}}
|
||||
>
|
||||
{((showStillWithoutActivity && !liveReady) || liveReady) && (
|
||||
<>
|
||||
<div className="pointer-events-none absolute inset-x-0 top-0 z-10 h-[30%] w-full rounded-lg bg-gradient-to-b from-black/20 to-transparent md:rounded-2xl"></div>
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-[10%] w-full rounded-lg bg-gradient-to-t from-black/20 to-transparent md:rounded-2xl"></div>
|
||||
</>
|
||||
)}
|
||||
{cameraEnabled &&
|
||||
((showStillWithoutActivity && !liveReady) || liveReady) && (
|
||||
<>
|
||||
<div className="pointer-events-none absolute inset-x-0 top-0 z-10 h-[30%] w-full rounded-lg bg-gradient-to-b from-black/20 to-transparent md:rounded-2xl"></div>
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-[10%] w-full rounded-lg bg-gradient-to-t from-black/20 to-transparent md:rounded-2xl"></div>
|
||||
</>
|
||||
)}
|
||||
{player}
|
||||
{!offline && !showStillWithoutActivity && !liveReady && (
|
||||
<ActivityIndicator />
|
||||
)}
|
||||
{cameraEnabled &&
|
||||
!offline &&
|
||||
(!showStillWithoutActivity || isReEnabling) &&
|
||||
!liveReady && <ActivityIndicator />}
|
||||
|
||||
{((showStillWithoutActivity && !liveReady) || liveReady) &&
|
||||
objects.length > 0 && (
|
||||
@@ -344,7 +393,9 @@ export default function LivePlayer({
|
||||
<div
|
||||
className={cn(
|
||||
"absolute inset-0 w-full",
|
||||
showStillWithoutActivity && !liveReady ? "visible" : "invisible",
|
||||
showStillWithoutActivity && !liveReady && !isReEnabling
|
||||
? "visible"
|
||||
: "invisible",
|
||||
)}
|
||||
>
|
||||
<AutoUpdatingCameraImage
|
||||
@@ -371,6 +422,17 @@ export default function LivePlayer({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!cameraEnabled && (
|
||||
<div className="relative flex h-full w-full items-center justify-center">
|
||||
<div className="flex h-32 flex-col items-center justify-center rounded-lg p-4 md:h-48 md:w-48">
|
||||
<LuVideoOff className="mb-2 size-8 md:size-10" />
|
||||
<p className="max-w-32 text-center text-sm md:max-w-40 md:text-base">
|
||||
Camera is disabled
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="absolute right-2 top-2">
|
||||
{autoLive &&
|
||||
!offline &&
|
||||
@@ -378,7 +440,7 @@ export default function LivePlayer({
|
||||
((showStillWithoutActivity && !liveReady) || liveReady) && (
|
||||
<MdCircle className="mr-2 size-2 animate-pulse text-danger shadow-danger drop-shadow-md" />
|
||||
)}
|
||||
{offline && showStillWithoutActivity && (
|
||||
{((offline && showStillWithoutActivity) || !cameraEnabled) && (
|
||||
<Chip
|
||||
className={`z-0 flex items-start justify-between space-x-1 bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 text-xs capitalize`}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user