mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-11-14 17:43:01 +03:00
Compare commits
4
Commits
519f3108dd
...
23fa08970f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23fa08970f | ||
|
|
e2ce0c82ff | ||
|
|
1ec511b66c | ||
|
|
7739a330d8 |
@@ -671,7 +671,7 @@ lpr:
|
||||
3. Ensure your plates are being _detected_.
|
||||
|
||||
If you are using a Frigate+ or `license_plate` detecting model:
|
||||
- Watch the debug view (Settings --> Debug) to ensure that `license_plate` is being detected.
|
||||
- Watch the [Debug view](/usage/live#the-single-camera-view) to ensure that `license_plate` is being detected.
|
||||
- View MQTT messages for `frigate/events` to verify detected plates.
|
||||
- You may need to adjust your `min_score` and/or `threshold` for the `license_plate` object if your plates are not being detected.
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@ import NavPath from "@site/src/components/NavPath";
|
||||
|
||||
This page describes how to _use_ the Explore view. For how the underlying features are _configured_, see [Semantic Search](/configuration/semantic_search) and [Generative AI descriptions](/configuration/genai/genai_objects).
|
||||
|
||||
:::tip
|
||||
|
||||
If you just want to quickly see what happened on your cameras, it's recommended to use [Review](/usage/review) rather than Explore. Review groups overlapping and adjacent activity on a camera into **review items** and sorts them into Alerts, Detections, and Motion, so you can scan and play back footage in a few clicks instead of sifting through individual objects. Reach for Explore when you need to find a _specific_ tracked object after the fact — by label, time, zone, or description.
|
||||
|
||||
:::
|
||||
|
||||
## Browsing tracked objects
|
||||
|
||||
The default view shows your most recent tracked objects grouped into rows by label — _Person_, _Car_, _Dog_, and so on — each row labeled with the object type and a count. The arrow at the end of a row opens the full, filterable grid for that label.
|
||||
|
||||
@@ -13,7 +13,7 @@ This page describes how to _use_ the Live view. For how to _configure_ live stre
|
||||
|
||||
The default **All Cameras** dashboard shows every camera, with a filmstrip of recent **alerts** scrolling across the top. Clicking an alert opens it in [Review](/usage/review); each card also has a check button to mark it reviewed without leaving the dashboard. Only **alerts** appear in the filmstrip — to suppress a label or zone from showing there, configure it as a detection instead (see [Alerts and Detections](/configuration/review#alerts-and-detections)).
|
||||
|
||||
By default Frigate uses **smart streaming**: a camera's image updates roughly once per minute while nothing is happening, and switches to a full live stream the moment activity is detected. This conserves bandwidth and resources. You can change this per camera or per group (see [Streaming settings](#streaming-settings-and-the-right-click-menu) below), and the behavior is explained in detail under [Live view technologies](/configuration/live#live-view-technologies).
|
||||
By default Frigate uses **smart streaming**: a camera's image updates roughly once per minute while nothing is happening, and switches to a full live stream the moment activity is detected. This conserves bandwidth and resources. You can change this for each camera when using a camera group (see [Streaming settings](#streaming-settings-and-the-right-click-menu) below), and the behavior is explained in detail under [Live view technologies](/configuration/live#live-view-technologies).
|
||||
|
||||
On mobile, a toggle in the header switches between a **grid** layout and a single-column **list** layout. On desktop a **fullscreen** button is available in the lower-right corner.
|
||||
|
||||
@@ -24,7 +24,7 @@ The icon rail (top-left on desktop, a horizontal strip on mobile) switches betwe
|
||||
- The **home** icon is the **All Cameras** dashboard, which shows every camera enabled for the dashboard.
|
||||
- Each **camera group** you create appears as its own icon. Selecting a group shows only that group's cameras.
|
||||
|
||||
Camera groups are useful for organizing cameras by location (for example, _Front of House_ or _Backyard_) and for giving each group its own dashboard layout and streaming preferences.
|
||||
Camera groups are useful for organizing cameras by location (for example, _Front of House_ or _Backyard_) and for giving each group its own dashboard layout and camera streaming preferences.
|
||||
|
||||
You can also view [Birdseye](/configuration/birdseye) on the dashboard, or open it directly at `http://<frigate_host>:5000/#birdseye`. Clicking a camera inside the Birdseye view jumps to that camera's live feed.
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
},
|
||||
"state": {
|
||||
"submitted": "Submitted"
|
||||
},
|
||||
"toast": {
|
||||
"error": "Failed to submit to Frigate+. Please check your network connection and try again."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,6 +116,7 @@ const detect: SectionConfigOverrides = {
|
||||
messageKey: "configMessages.detect.fpsGreaterThanFive",
|
||||
severity: "info",
|
||||
position: "after",
|
||||
docLink: "/frigate/camera_setup#choosing-a-detect-frame-rate",
|
||||
condition: (ctx) => {
|
||||
if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
|
||||
if (ctx.fullCameraConfig.type === "lpr") return false;
|
||||
|
||||
@@ -11,6 +11,9 @@ import useSWR from "swr";
|
||||
import { useTimeFormat } from "@/hooks/use-date-utils";
|
||||
|
||||
const GRAPH_COLORS = ["#5C7CFA", "#ED5CFA", "#FAD75C"];
|
||||
// Distinct palette so the Frames / Detections graphs are easy to tell apart
|
||||
// from the CPU graphs at a glance.
|
||||
export const FPS_GRAPH_COLORS = ["#2DD4BF", "#818CFF", "#D17B88"];
|
||||
|
||||
type CameraLineGraphProps = {
|
||||
graphId: string;
|
||||
@@ -19,6 +22,7 @@ type CameraLineGraphProps = {
|
||||
updateTimes: number[];
|
||||
data: ApexAxisChartSeries;
|
||||
isActive?: boolean;
|
||||
colors?: string[];
|
||||
};
|
||||
export function CameraLineGraph({
|
||||
graphId,
|
||||
@@ -27,6 +31,7 @@ export function CameraLineGraph({
|
||||
updateTimes,
|
||||
data,
|
||||
isActive = true,
|
||||
colors = GRAPH_COLORS,
|
||||
}: CameraLineGraphProps) {
|
||||
const { t } = useTranslation(["views/system", "common"]);
|
||||
const { data: config } = useSWR<FrigateConfig>("config", {
|
||||
@@ -91,7 +96,7 @@ export function CameraLineGraph({
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
colors: GRAPH_COLORS,
|
||||
colors,
|
||||
grid: {
|
||||
show: false,
|
||||
},
|
||||
@@ -138,7 +143,7 @@ export function CameraLineGraph({
|
||||
min: 0,
|
||||
},
|
||||
} as ApexCharts.ApexOptions;
|
||||
}, [graphId, systemTheme, theme, formatTime]);
|
||||
}, [graphId, colors, systemTheme, theme, formatTime]);
|
||||
|
||||
useEffect(() => {
|
||||
ApexCharts.exec(graphId, "updateOptions", options, true, true);
|
||||
@@ -162,7 +167,7 @@ export function CameraLineGraph({
|
||||
<div key={label} className="flex items-center gap-1">
|
||||
<MdCircle
|
||||
className="size-2"
|
||||
style={{ color: GRAPH_COLORS[labelIdx] }}
|
||||
style={{ color: colors[labelIdx] }}
|
||||
/>
|
||||
<div className="text-xs text-secondary-foreground">
|
||||
{t("cameras.label." + label)}
|
||||
|
||||
@@ -1251,30 +1251,42 @@ function ObjectDetailsTab({
|
||||
return;
|
||||
}
|
||||
|
||||
falsePositive
|
||||
? axios.put(`events/${search.id}/false_positive`)
|
||||
: axios.post(`events/${search.id}/plus`, {
|
||||
include_annotation: 1,
|
||||
});
|
||||
try {
|
||||
const resp = falsePositive
|
||||
? await axios.put(`events/${search.id}/false_positive`)
|
||||
: await axios.post(`events/${search.id}/plus`, {
|
||||
include_annotation: 1,
|
||||
});
|
||||
|
||||
setState("submitted");
|
||||
setSearch({ ...search, plus_id: "new_upload" });
|
||||
mutate(
|
||||
(key) => isEventsKey(key),
|
||||
(currentData: SearchResult[][] | SearchResult[] | undefined) =>
|
||||
mapSearchResults(currentData, (event) =>
|
||||
event.id === search.id
|
||||
? { ...event, plus_id: "new_upload" }
|
||||
: event,
|
||||
),
|
||||
{
|
||||
optimisticData: true,
|
||||
rollbackOnError: true,
|
||||
revalidate: false,
|
||||
},
|
||||
);
|
||||
if (resp.status !== 200 || !resp.data?.success) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
setState("submitted");
|
||||
setSearch({ ...search, plus_id: "new_upload" });
|
||||
mutate(
|
||||
(key) => isEventsKey(key),
|
||||
(currentData: SearchResult[][] | SearchResult[] | undefined) =>
|
||||
mapSearchResults(currentData, (event) =>
|
||||
event.id === search.id
|
||||
? { ...event, plus_id: "new_upload" }
|
||||
: event,
|
||||
),
|
||||
{
|
||||
optimisticData: true,
|
||||
rollbackOnError: true,
|
||||
revalidate: false,
|
||||
},
|
||||
);
|
||||
} catch {
|
||||
setState("reviewing");
|
||||
toast.error(
|
||||
t("explore.plus.review.toast.error", { ns: "components/dialog" }),
|
||||
{ position: "top-center" },
|
||||
);
|
||||
}
|
||||
},
|
||||
[search, mutate, mapSearchResults, setSearch, isEventsKey],
|
||||
[search, mutate, mapSearchResults, setSearch, isEventsKey, t],
|
||||
);
|
||||
|
||||
const popoverContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -1225,11 +1225,15 @@ function LifecycleIconRow({
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onSelect={async () => {
|
||||
const resp = await axios.post(
|
||||
`/${item.camera}/plus/${item.timestamp + annotationOffset / 1000}`,
|
||||
);
|
||||
try {
|
||||
const resp = await axios.post(
|
||||
`/${item.camera}/plus/${item.timestamp + annotationOffset / 1000}`,
|
||||
);
|
||||
|
||||
if (resp.status !== 200) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (resp && resp.status == 200) {
|
||||
toast.success(
|
||||
t("toast.success.submittedFrigatePlus", {
|
||||
ns: "components/player",
|
||||
@@ -1238,8 +1242,8 @@ function LifecycleIconRow({
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
} else {
|
||||
toast.success(
|
||||
} catch {
|
||||
toast.error(
|
||||
t("toast.error.submitFrigatePlusFailed", {
|
||||
ns: "components/player",
|
||||
}),
|
||||
|
||||
@@ -10,6 +10,7 @@ import { isDesktop, isMobile, isSafari } from "react-device-detect";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
@@ -48,13 +49,28 @@ export function FrigatePlusDialog({
|
||||
const onSubmitToPlus = useCallback(
|
||||
async (falsePositive: boolean) => {
|
||||
if (!upload) return;
|
||||
falsePositive
|
||||
? axios.put(`events/${upload.id}/false_positive`)
|
||||
: axios.post(`events/${upload.id}/plus`, { include_annotation: 1 });
|
||||
setState("submitted");
|
||||
onEventUploaded();
|
||||
|
||||
try {
|
||||
const resp = falsePositive
|
||||
? await axios.put(`events/${upload.id}/false_positive`)
|
||||
: await axios.post(`events/${upload.id}/plus`, {
|
||||
include_annotation: 1,
|
||||
});
|
||||
|
||||
if (resp.status !== 200 || !resp.data?.success) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
setState("submitted");
|
||||
onEventUploaded();
|
||||
} catch {
|
||||
setState("reviewing");
|
||||
toast.error(t("explore.plus.review.toast.error"), {
|
||||
position: "top-center",
|
||||
});
|
||||
}
|
||||
},
|
||||
[upload, onEventUploaded],
|
||||
[upload, onEventUploaded, t],
|
||||
);
|
||||
|
||||
const [imgRef, imgLoaded, onImgLoad] = useImageLoaded();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useFrigateStats } from "@/api/ws";
|
||||
import { CameraLineGraph } from "@/components/graph/LineGraph";
|
||||
import {
|
||||
CameraLineGraph,
|
||||
FPS_GRAPH_COLORS,
|
||||
} from "@/components/graph/LineGraph";
|
||||
import CameraInfoDialog from "@/components/overlay/CameraInfoDialog";
|
||||
import { ConnectionQualityIndicator } from "@/components/camera/ConnectionQualityIndicator";
|
||||
import { EmptyCard } from "@/components/card/EmptyCard";
|
||||
@@ -308,6 +311,7 @@ export default function CameraMetrics({
|
||||
updateTimes={updateTimes}
|
||||
data={overallFpsSeries}
|
||||
isActive={isActive}
|
||||
colors={FPS_GRAPH_COLORS}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
@@ -411,6 +415,7 @@ export default function CameraMetrics({
|
||||
cameraFpsSeries[camera.name] || {},
|
||||
)}
|
||||
isActive={isActive}
|
||||
colors={FPS_GRAPH_COLORS}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user