mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-12 06:05:22 +03:00
Implement non auto live
This commit is contained in:
parent
623eee2202
commit
e3a7d6a506
@ -17,6 +17,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
type LivePlayerProps = {
|
type LivePlayerProps = {
|
||||||
cameraRef?: (ref: HTMLDivElement | null) => void;
|
cameraRef?: (ref: HTMLDivElement | null) => void;
|
||||||
|
containerRef?: React.MutableRefObject<HTMLDivElement | null>;
|
||||||
className?: string;
|
className?: string;
|
||||||
cameraConfig: CameraConfig;
|
cameraConfig: CameraConfig;
|
||||||
preferredLiveMode?: LivePlayerMode;
|
preferredLiveMode?: LivePlayerMode;
|
||||||
@ -26,13 +27,14 @@ type LivePlayerProps = {
|
|||||||
micEnabled?: boolean; // only webrtc supports mic
|
micEnabled?: boolean; // only webrtc supports mic
|
||||||
iOSCompatFullScreen?: boolean;
|
iOSCompatFullScreen?: boolean;
|
||||||
pip?: boolean;
|
pip?: boolean;
|
||||||
|
autoLive?: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
||||||
containerRef?: React.MutableRefObject<HTMLDivElement | null>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LivePlayer({
|
export default function LivePlayer({
|
||||||
cameraRef = undefined,
|
cameraRef = undefined,
|
||||||
|
containerRef,
|
||||||
className,
|
className,
|
||||||
cameraConfig,
|
cameraConfig,
|
||||||
preferredLiveMode,
|
preferredLiveMode,
|
||||||
@ -42,9 +44,9 @@ export default function LivePlayer({
|
|||||||
micEnabled = false,
|
micEnabled = false,
|
||||||
iOSCompatFullScreen = false,
|
iOSCompatFullScreen = false,
|
||||||
pip,
|
pip,
|
||||||
|
autoLive = true,
|
||||||
onClick,
|
onClick,
|
||||||
setFullResolution,
|
setFullResolution,
|
||||||
containerRef,
|
|
||||||
}: LivePlayerProps) {
|
}: LivePlayerProps) {
|
||||||
// camera activity
|
// camera activity
|
||||||
|
|
||||||
@ -64,6 +66,10 @@ export default function LivePlayer({
|
|||||||
|
|
||||||
const [liveReady, setLiveReady] = useState(false);
|
const [liveReady, setLiveReady] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!autoLive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!liveReady) {
|
if (!liveReady) {
|
||||||
if (cameraActive && liveMode == "jsmpeg") {
|
if (cameraActive && liveMode == "jsmpeg") {
|
||||||
setLiveReady(true);
|
setLiveReady(true);
|
||||||
@ -77,7 +83,7 @@ export default function LivePlayer({
|
|||||||
}
|
}
|
||||||
// live mode won't change
|
// live mode won't change
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [cameraActive, liveReady]);
|
}, [autoLive, cameraActive, liveReady]);
|
||||||
|
|
||||||
// camera still state
|
// camera still state
|
||||||
|
|
||||||
@ -91,18 +97,31 @@ export default function LivePlayer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (activeMotion || activeTracking) {
|
if (activeMotion || activeTracking) {
|
||||||
return 200;
|
if (autoLive) {
|
||||||
|
return 200;
|
||||||
|
} else {
|
||||||
|
return 59000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 30000;
|
return 30000;
|
||||||
}, [liveReady, activeMotion, activeTracking, offline, windowVisible]);
|
}, [
|
||||||
|
autoLive,
|
||||||
|
liveReady,
|
||||||
|
activeMotion,
|
||||||
|
activeTracking,
|
||||||
|
offline,
|
||||||
|
windowVisible,
|
||||||
|
]);
|
||||||
|
|
||||||
if (!cameraConfig) {
|
if (!cameraConfig) {
|
||||||
return <ActivityIndicator />;
|
return <ActivityIndicator />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let player;
|
let player;
|
||||||
if (liveMode == "webrtc") {
|
if (!autoLive) {
|
||||||
|
player = null;
|
||||||
|
} else if (liveMode == "webrtc") {
|
||||||
player = (
|
player = (
|
||||||
<WebRtcPlayer
|
<WebRtcPlayer
|
||||||
className={`size-full rounded-lg md:rounded-2xl ${liveReady ? "" : "hidden"}`}
|
className={`size-full rounded-lg md:rounded-2xl ${liveReady ? "" : "hidden"}`}
|
||||||
|
|||||||
@ -50,6 +50,7 @@ export default function LiveDashboardView({
|
|||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// recent events
|
// recent events
|
||||||
|
|
||||||
const { payload: eventUpdate } = useFrigateReviews();
|
const { payload: eventUpdate } = useFrigateReviews();
|
||||||
const { data: allEvents, mutate: updateEvents } = useSWR<ReviewSegment[]>([
|
const { data: allEvents, mutate: updateEvents } = useSWR<ReviewSegment[]>([
|
||||||
"review",
|
"review",
|
||||||
@ -92,6 +93,7 @@ export default function LiveDashboardView({
|
|||||||
|
|
||||||
// camera live views
|
// camera live views
|
||||||
|
|
||||||
|
const [autoLiveView] = usePersistence("autoLiveView");
|
||||||
const [windowVisible, setWindowVisible] = useState(true);
|
const [windowVisible, setWindowVisible] = useState(true);
|
||||||
const visibilityListener = useCallback(() => {
|
const visibilityListener = useCallback(() => {
|
||||||
setWindowVisible(document.visibilityState == "visible");
|
setWindowVisible(document.visibilityState == "visible");
|
||||||
|
|||||||
@ -49,6 +49,9 @@ export default function GeneralSettingsView() {
|
|||||||
document.title = "General Settings - Frigate";
|
document.title = "General Settings - Frigate";
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// settings
|
||||||
|
|
||||||
|
const [autoLive, setAutoLive] = usePersistence("autoLiveView", true);
|
||||||
const [playbackRate, setPlaybackRate] = usePersistence("playbackRate", 1);
|
const [playbackRate, setPlaybackRate] = usePersistence("playbackRate", 1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -60,7 +63,33 @@ export default function GeneralSettingsView() {
|
|||||||
General Settings
|
General Settings
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<div className="flex w-full flex-col space-y-6">
|
<Separator className="my-2 flex bg-secondary" />
|
||||||
|
|
||||||
|
<Heading as="h4" className="my-2">
|
||||||
|
Dashboard
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<div className="mt-2 space-y-6">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex flex-row items-center justify-start gap-2">
|
||||||
|
<Switch
|
||||||
|
id="auto-live"
|
||||||
|
checked={autoLive}
|
||||||
|
onCheckedChange={setAutoLive}
|
||||||
|
/>
|
||||||
|
<Label className="cursor-pointer" htmlFor="auto-live">
|
||||||
|
Automatic Live View
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="my-2 text-sm text-muted-foreground">
|
||||||
|
<p>
|
||||||
|
Automatically switch to live view when motion is detected.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="my-3 flex w-full flex-col space-y-6">
|
||||||
<div className="mt-2 space-y-6">
|
<div className="mt-2 space-y-6">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<div className="text-md">Stored Layouts</div>
|
<div className="text-md">Stored Layouts</div>
|
||||||
@ -72,11 +101,15 @@ export default function GeneralSettingsView() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-start gap-2">
|
<Button onClick={clearStoredLayouts}>Clear All Layouts</Button>
|
||||||
<Button onClick={clearStoredLayouts}>Clear All Layouts</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Separator className="my-2 flex bg-secondary" />
|
<Separator className="my-2 flex bg-secondary" />
|
||||||
|
|
||||||
|
<Heading as="h4" className="my-2">
|
||||||
|
Recordings Viewer
|
||||||
|
</Heading>
|
||||||
|
|
||||||
<div className="mt-2 space-y-6">
|
<div className="mt-2 space-y-6">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<div className="text-md">Default Playback Rate</div>
|
<div className="text-md">Default Playback Rate</div>
|
||||||
@ -107,26 +140,6 @@ export default function GeneralSettingsView() {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Separator className="my-2 flex bg-secondary" />
|
<Separator className="my-2 flex bg-secondary" />
|
||||||
<div className="mt-2 space-y-6">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<div className="text-md">Low Data Mode</div>
|
|
||||||
<div className="my-2 text-sm text-muted-foreground">
|
|
||||||
<p>
|
|
||||||
Not yet implemented. <em>Default: disabled</em>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row items-center justify-start gap-2">
|
|
||||||
<Switch
|
|
||||||
id="lowdata"
|
|
||||||
checked={false}
|
|
||||||
onCheckedChange={() => {}}
|
|
||||||
/>
|
|
||||||
<Label htmlFor="lowdata">
|
|
||||||
Low Data Mode (this device only)
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { PolygonCanvas } from "./PolygonCanvas";
|
import { PolygonCanvas } from "@/components/settings/PolygonCanvas";
|
||||||
import { Polygon, PolygonType } from "@/types/canvas";
|
import { Polygon, PolygonType } from "@/types/canvas";
|
||||||
import { interpolatePoints, parseCoordinates } from "@/utils/canvasUtil";
|
import { interpolatePoints, parseCoordinates } from "@/utils/canvasUtil";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user