mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 21:44:13 +03:00
Adjust threat level interaction to be less strict
This commit is contained in:
parent
890ae6ae50
commit
376e5b5c25
@ -375,7 +375,19 @@ class WebPushClient(Communicator):
|
|||||||
ended = state == "end" or state == "genai"
|
ended = state == "end" or state == "genai"
|
||||||
|
|
||||||
if state == "genai" and payload["after"]["data"]["metadata"]:
|
if state == "genai" and payload["after"]["data"]["metadata"]:
|
||||||
title = payload["after"]["data"]["metadata"]["title"]
|
base_title = payload["after"]["data"]["metadata"]["title"]
|
||||||
|
threat_level = payload["after"]["data"]["metadata"].get(
|
||||||
|
"potential_threat_level", 0
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add prefix for threat levels 1 and 2
|
||||||
|
if threat_level == 1:
|
||||||
|
title = f"Needs Review: {base_title}"
|
||||||
|
elif threat_level == 2:
|
||||||
|
title = f"Security Concern: {base_title}"
|
||||||
|
else:
|
||||||
|
title = base_title
|
||||||
|
|
||||||
message = payload["after"]["data"]["metadata"]["scene"]
|
message = payload["after"]["data"]["metadata"]["scene"]
|
||||||
else:
|
else:
|
||||||
title = f"{titlecase(', '.join(sorted_objects).replace('_', ' '))}{' was' if state == 'end' else ''} detected in {titlecase(', '.join(payload['after']['data']['zones']).replace('_', ' '))}"
|
title = f"{titlecase(', '.join(sorted_objects).replace('_', ' '))}{' was' if state == 'end' else ''} detected in {titlecase(', '.join(payload['after']['data']['zones']).replace('_', ' '))}"
|
||||||
|
|||||||
@ -205,14 +205,20 @@ Rules for the report:
|
|||||||
- Group bullets under subheadings when multiple events fall into the same category (e.g., Vehicle Activity, Porch Activity, Unusual Behavior).
|
- Group bullets under subheadings when multiple events fall into the same category (e.g., Vehicle Activity, Porch Activity, Unusual Behavior).
|
||||||
|
|
||||||
- Threat levels
|
- Threat levels
|
||||||
- Always show (threat level: X) for each event.
|
- Always show the threat level for each event using these labels:
|
||||||
|
- Threat level 0: "Normal"
|
||||||
|
- Threat level 1: "Needs review"
|
||||||
|
- Threat level 2: "Security concern"
|
||||||
|
- Format as (threat level: Normal), (threat level: Needs review), or (threat level: Security concern).
|
||||||
- If multiple events at the same time share the same threat level, only state it once.
|
- If multiple events at the same time share the same threat level, only state it once.
|
||||||
|
|
||||||
- Final assessment
|
- Final assessment
|
||||||
- End with a Final Assessment section.
|
- End with a Final Assessment section.
|
||||||
- If all events are threat level 1 with no escalation:
|
- If all events are threat level 0:
|
||||||
Final assessment: Only normal residential activity observed during this period.
|
Final assessment: Only normal residential activity observed during this period.
|
||||||
- If threat level 2+ events are present, clearly summarize them as Potential concerns requiring review.
|
- If threat level 1 events are present:
|
||||||
|
Final assessment: Some activity requires review but no security concerns identified.
|
||||||
|
- If threat level 2 events are present, clearly summarize them as Security concerns requiring immediate attention.
|
||||||
|
|
||||||
- Conciseness
|
- Conciseness
|
||||||
- Do not repeat benign clothing/appearance details unless they distinguish individuals.
|
- Do not repeat benign clothing/appearance details unless they distinguish individuals.
|
||||||
|
|||||||
@ -54,6 +54,7 @@
|
|||||||
"selected_other": "{{count}} selected",
|
"selected_other": "{{count}} selected",
|
||||||
"camera": "Camera",
|
"camera": "Camera",
|
||||||
"detected": "detected",
|
"detected": "detected",
|
||||||
"suspiciousActivity": "Suspicious Activity",
|
"normalActivity": "Normal",
|
||||||
"threateningActivity": "Threatening Activity"
|
"needsReview": "Needs review",
|
||||||
|
"securityConcern": "Security concern"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||||
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { ReviewSegment, ThreatLevel } from "@/types/review";
|
import {
|
||||||
|
ReviewSegment,
|
||||||
|
ThreatLevel,
|
||||||
|
THREAT_LEVEL_LABELS,
|
||||||
|
} from "@/types/review";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { isDesktop } from "react-device-detect";
|
import { isDesktop } from "react-device-detect";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -55,13 +59,22 @@ export function GenAISummaryDialog({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let concerns = "";
|
let concerns = "";
|
||||||
switch (aiAnalysis.potential_threat_level) {
|
const threatLevel = aiAnalysis.potential_threat_level ?? 0;
|
||||||
case ThreatLevel.SUSPICIOUS:
|
|
||||||
concerns = `• ${t("suspiciousActivity", { ns: "views/events" })}\n`;
|
if (threatLevel > 0) {
|
||||||
|
let label = "";
|
||||||
|
|
||||||
|
switch (threatLevel) {
|
||||||
|
case ThreatLevel.NEEDS_REVIEW:
|
||||||
|
label = t("needsReview", { ns: "views/events" });
|
||||||
break;
|
break;
|
||||||
case ThreatLevel.DANGER:
|
case ThreatLevel.SECURITY_CONCERN:
|
||||||
concerns = `• ${t("threateningActivity", { ns: "views/events" })}\n`;
|
label = t("securityConcern", { ns: "views/events" });
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
label = THREAT_LEVEL_LABELS[threatLevel as ThreatLevel] || "Unknown";
|
||||||
|
}
|
||||||
|
concerns = `• ${label}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
(aiAnalysis.other_concerns ?? []).forEach((c) => {
|
(aiAnalysis.other_concerns ?? []).forEach((c) => {
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useApiHost } from "@/api";
|
import { useApiHost } from "@/api";
|
||||||
import { isCurrentHour } from "@/utils/dateUtil";
|
import { isCurrentHour } from "@/utils/dateUtil";
|
||||||
import { ReviewSegment } from "@/types/review";
|
import {
|
||||||
|
ReviewSegment,
|
||||||
|
ThreatLevel,
|
||||||
|
THREAT_LEVEL_LABELS,
|
||||||
|
} from "@/types/review";
|
||||||
import { getIconForLabel } from "@/utils/iconUtil";
|
import { getIconForLabel } from "@/utils/iconUtil";
|
||||||
import TimeAgo from "../dynamic/TimeAgo";
|
import TimeAgo from "../dynamic/TimeAgo";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
@ -44,7 +48,7 @@ export default function PreviewThumbnailPlayer({
|
|||||||
onClick,
|
onClick,
|
||||||
onTimeUpdate,
|
onTimeUpdate,
|
||||||
}: PreviewPlayerProps) {
|
}: PreviewPlayerProps) {
|
||||||
const { t } = useTranslation(["components/player"]);
|
const { t } = useTranslation(["components/player", "views/events"]);
|
||||||
const apiHost = useApiHost();
|
const apiHost = useApiHost();
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const [imgRef, imgLoaded, onImgLoad] = useImageLoaded();
|
const [imgRef, imgLoaded, onImgLoad] = useImageLoaded();
|
||||||
@ -319,11 +323,21 @@ export default function PreviewThumbnailPlayer({
|
|||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
</div>
|
</div>
|
||||||
<TooltipContent className="smart-capitalize">
|
<TooltipContent className="smart-capitalize">
|
||||||
{review.data.metadata.potential_threat_level == 1 ? (
|
{(() => {
|
||||||
<>{t("suspiciousActivity", { ns: "views/events" })}</>
|
const threatLevel =
|
||||||
) : (
|
review.data.metadata.potential_threat_level ?? 0;
|
||||||
<>{t("threateningActivity", { ns: "views/events" })}</>
|
switch (threatLevel) {
|
||||||
)}
|
case ThreatLevel.NEEDS_REVIEW:
|
||||||
|
return t("needsReview", { ns: "views/events" });
|
||||||
|
case ThreatLevel.SECURITY_CONCERN:
|
||||||
|
return t("securityConcern", { ns: "views/events" });
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
THREAT_LEVEL_LABELS[threatLevel as ThreatLevel] ||
|
||||||
|
"Unknown"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -87,6 +87,13 @@ export type ZoomLevel = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export enum ThreatLevel {
|
export enum ThreatLevel {
|
||||||
SUSPICIOUS = 1,
|
NORMAL = 0,
|
||||||
DANGER = 2,
|
NEEDS_REVIEW = 1,
|
||||||
|
SECURITY_CONCERN = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const THREAT_LEVEL_LABELS: Record<ThreatLevel, string> = {
|
||||||
|
[ThreatLevel.NORMAL]: "Normal",
|
||||||
|
[ThreatLevel.NEEDS_REVIEW]: "Needs review",
|
||||||
|
[ThreatLevel.SECURITY_CONCERN]: "Security concern",
|
||||||
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user