2025-10-26 16:40:38 +03:00
|
|
|
from enum import Enum
|
2024-09-28 22:21:42 +03:00
|
|
|
from typing import Optional, Union
|
|
|
|
|
|
|
|
|
|
from pydantic import Field, field_validator
|
|
|
|
|
|
|
|
|
|
from ..base import FrigateBaseModel
|
|
|
|
|
|
2025-10-26 16:40:38 +03:00
|
|
|
__all__ = ["ReviewConfig", "DetectionsConfig", "AlertsConfig", "ImageSourceEnum"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ImageSourceEnum(str, Enum):
|
|
|
|
|
"""Image source options for GenAI Review."""
|
|
|
|
|
|
|
|
|
|
preview = "preview"
|
|
|
|
|
recordings = "recordings"
|
2024-09-28 22:21:42 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
DEFAULT_ALERT_OBJECTS = ["person", "car"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AlertsConfig(FrigateBaseModel):
|
|
|
|
|
"""Configure alerts"""
|
|
|
|
|
|
2026-02-27 18:55:36 +03:00
|
|
|
enabled: bool = Field(
|
|
|
|
|
default=True,
|
|
|
|
|
title="Enable alerts",
|
|
|
|
|
description="Enable or disable alert generation for all cameras; can be overridden per-camera.",
|
|
|
|
|
)
|
2025-02-11 17:46:25 +03:00
|
|
|
|
2024-09-28 22:21:42 +03:00
|
|
|
labels: list[str] = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default=DEFAULT_ALERT_OBJECTS,
|
|
|
|
|
title="Alert labels",
|
|
|
|
|
description="List of object labels that qualify as alerts (for example: car, person).",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
|
|
|
|
required_zones: Union[str, list[str]] = Field(
|
|
|
|
|
default_factory=list,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Required zones",
|
|
|
|
|
description="Zones that an object must enter to be considered an alert; leave empty to allow any zone.",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
|
|
|
|
|
2025-02-11 17:46:25 +03:00
|
|
|
enabled_in_config: Optional[bool] = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default=None,
|
|
|
|
|
title="Original alerts state",
|
|
|
|
|
description="Tracks whether alerts were originally enabled in the static configuration.",
|
2025-02-11 17:46:25 +03:00
|
|
|
)
|
2025-09-01 00:36:12 +03:00
|
|
|
cutoff_time: int = Field(
|
|
|
|
|
default=40,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Alerts cutoff time",
|
|
|
|
|
description="Seconds to wait after no alert-causing activity before cutting off an alert.",
|
2025-09-01 00:36:12 +03:00
|
|
|
)
|
2025-02-11 17:46:25 +03:00
|
|
|
|
2024-09-28 22:21:42 +03:00
|
|
|
@field_validator("required_zones", mode="before")
|
|
|
|
|
@classmethod
|
|
|
|
|
def validate_required_zones(cls, v):
|
|
|
|
|
if isinstance(v, str) and "," not in v:
|
|
|
|
|
return [v]
|
|
|
|
|
|
|
|
|
|
return v
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DetectionsConfig(FrigateBaseModel):
|
|
|
|
|
"""Configure detections"""
|
|
|
|
|
|
2026-02-27 18:55:36 +03:00
|
|
|
enabled: bool = Field(
|
|
|
|
|
default=True,
|
|
|
|
|
title="Enable detections",
|
|
|
|
|
description="Enable or disable detection events for all cameras; can be overridden per-camera.",
|
|
|
|
|
)
|
2025-02-11 17:46:25 +03:00
|
|
|
|
2024-09-28 22:21:42 +03:00
|
|
|
labels: Optional[list[str]] = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default=None,
|
|
|
|
|
title="Detection labels",
|
|
|
|
|
description="List of object labels that qualify as detection events.",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
|
|
|
|
required_zones: Union[str, list[str]] = Field(
|
|
|
|
|
default_factory=list,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Required zones",
|
|
|
|
|
description="Zones that an object must enter to be considered a detection; leave empty to allow any zone.",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
2025-09-01 00:36:12 +03:00
|
|
|
cutoff_time: int = Field(
|
|
|
|
|
default=30,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Detections cutoff time",
|
|
|
|
|
description="Seconds to wait after no detection-causing activity before cutting off a detection.",
|
2025-09-01 00:36:12 +03:00
|
|
|
)
|
2024-09-28 22:21:42 +03:00
|
|
|
|
2025-02-11 17:46:25 +03:00
|
|
|
enabled_in_config: Optional[bool] = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default=None,
|
|
|
|
|
title="Original detections state",
|
|
|
|
|
description="Tracks whether detections were originally enabled in the static configuration.",
|
2025-02-11 17:46:25 +03:00
|
|
|
)
|
|
|
|
|
|
2024-09-28 22:21:42 +03:00
|
|
|
@field_validator("required_zones", mode="before")
|
|
|
|
|
@classmethod
|
|
|
|
|
def validate_required_zones(cls, v):
|
|
|
|
|
if isinstance(v, str) and "," not in v:
|
|
|
|
|
return [v]
|
|
|
|
|
|
|
|
|
|
return v
|
|
|
|
|
|
|
|
|
|
|
2025-08-10 14:57:54 +03:00
|
|
|
class GenAIReviewConfig(FrigateBaseModel):
|
2025-08-10 16:38:04 +03:00
|
|
|
enabled: bool = Field(
|
|
|
|
|
default=False,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Enable GenAI descriptions",
|
|
|
|
|
description="Enable or disable GenAI-generated descriptions and summaries for review items.",
|
|
|
|
|
)
|
|
|
|
|
alerts: bool = Field(
|
|
|
|
|
default=True,
|
|
|
|
|
title="Enable GenAI for alerts",
|
|
|
|
|
description="Use GenAI to generate descriptions for alert items.",
|
|
|
|
|
)
|
|
|
|
|
detections: bool = Field(
|
|
|
|
|
default=False,
|
|
|
|
|
title="Enable GenAI for detections",
|
|
|
|
|
description="Use GenAI to generate descriptions for detection items.",
|
2025-08-10 16:38:04 +03:00
|
|
|
)
|
2025-10-26 16:40:38 +03:00
|
|
|
image_source: ImageSourceEnum = Field(
|
|
|
|
|
default=ImageSourceEnum.preview,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Review image source",
|
|
|
|
|
description="Source of images sent to GenAI ('preview' or 'recordings'); 'recordings' uses higher quality frames but more tokens.",
|
2025-10-26 16:40:38 +03:00
|
|
|
)
|
2025-08-11 22:17:25 +03:00
|
|
|
additional_concerns: list[str] = Field(
|
|
|
|
|
default=[],
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Additional concerns",
|
|
|
|
|
description="A list of additional concerns or notes the GenAI should consider when evaluating activity on this camera.",
|
2025-08-11 22:17:25 +03:00
|
|
|
)
|
2025-08-10 14:57:54 +03:00
|
|
|
debug_save_thumbnails: bool = Field(
|
|
|
|
|
default=False,
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Save thumbnails",
|
|
|
|
|
description="Save thumbnails that are sent to the GenAI provider for debugging and review.",
|
2025-08-10 14:57:54 +03:00
|
|
|
)
|
|
|
|
|
enabled_in_config: Optional[bool] = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default=None,
|
|
|
|
|
title="Original GenAI state",
|
|
|
|
|
description="Tracks whether GenAI review was originally enabled in the static configuration.",
|
2025-08-10 14:57:54 +03:00
|
|
|
)
|
2025-08-11 22:17:25 +03:00
|
|
|
preferred_language: str | None = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Preferred language",
|
|
|
|
|
description="Preferred language to request from the GenAI provider for generated responses.",
|
2025-08-11 22:17:25 +03:00
|
|
|
default=None,
|
|
|
|
|
)
|
2025-10-01 02:07:16 +03:00
|
|
|
activity_context_prompt: str = Field(
|
2025-10-27 19:34:39 +03:00
|
|
|
default="""### Normal Activity Indicators (Level 0)
|
2025-10-30 17:52:55 +03:00
|
|
|
- Known/verified people in any zone at any time
|
2025-10-27 19:34:39 +03:00
|
|
|
- People with pets in residential areas
|
2026-02-03 17:31:00 +03:00
|
|
|
- Routine residential vehicle access during daytime/evening (6 AM - 10 PM): entering, exiting, loading/unloading items — normal commute and travel patterns
|
2025-10-30 17:52:55 +03:00
|
|
|
- Deliveries or services during daytime/evening (6 AM - 10 PM): carrying packages to doors/porches, placing items, leaving
|
|
|
|
|
- Services/maintenance workers with visible tools, uniforms, or service vehicles during daytime
|
|
|
|
|
- Activity confined to public areas only (sidewalks, streets) without entering property at any time
|
2025-10-27 19:34:39 +03:00
|
|
|
|
|
|
|
|
### Suspicious Activity Indicators (Level 1)
|
2026-02-03 17:31:00 +03:00
|
|
|
- **Checking or probing vehicle/building access**: trying handles without entering, peering through windows, examining multiple vehicles, or possessing break-in tools — Level 1
|
2025-10-30 17:52:55 +03:00
|
|
|
- **Unidentified person in private areas (driveways, near vehicles/buildings) during late night/early morning (11 PM - 5 AM)** — ALWAYS Level 1 regardless of activity or duration
|
|
|
|
|
- Taking items that don't belong to them (packages, objects from porches/driveways)
|
2025-10-28 16:28:36 +03:00
|
|
|
- Climbing or jumping fences/barriers to access property
|
|
|
|
|
- Attempting to conceal actions or items from view
|
2025-10-30 17:52:55 +03:00
|
|
|
- Prolonged loitering: remaining in same area without visible purpose throughout most of the sequence
|
2025-10-27 19:34:39 +03:00
|
|
|
|
|
|
|
|
### Critical Threat Indicators (Level 2)
|
|
|
|
|
- Holding break-in tools (crowbars, pry bars, bolt cutters)
|
|
|
|
|
- Weapons visible (guns, knives, bats used aggressively)
|
|
|
|
|
- Forced entry in progress
|
|
|
|
|
- Physical aggression or violence
|
2025-10-30 17:52:55 +03:00
|
|
|
- Active property damage or theft in progress
|
2025-10-27 19:34:39 +03:00
|
|
|
|
|
|
|
|
### Assessment Guidance
|
2025-10-30 17:52:55 +03:00
|
|
|
Evaluate in this order:
|
2025-10-28 16:28:36 +03:00
|
|
|
|
2025-10-30 17:52:55 +03:00
|
|
|
1. **If person is verified/known** → Level 0 regardless of time or activity
|
|
|
|
|
2. **If person is unidentified:**
|
|
|
|
|
- Check time: If late night/early morning (11 PM - 5 AM) AND in private areas (driveways, near vehicles/buildings) → Level 1
|
2026-02-03 17:31:00 +03:00
|
|
|
- Check actions: If probing access (trying handles without entering, checking multiple vehicles), taking items, climbing → Level 1
|
|
|
|
|
- Otherwise, if daytime/evening (6 AM - 10 PM) with clear legitimate purpose (delivery, service, routine vehicle access) → Level 0
|
2025-10-30 17:52:55 +03:00
|
|
|
3. **Escalate to Level 2 if:** Weapons, break-in tools, forced entry in progress, violence, or active property damage visible (escalates from Level 0 or 1)
|
2025-10-29 17:40:50 +03:00
|
|
|
|
2025-10-30 17:52:55 +03:00
|
|
|
The mere presence of an unidentified person in private areas during late night hours is inherently suspicious and warrants human review, regardless of what activity they appear to be doing or how brief the sequence is.""",
|
2026-02-27 18:55:36 +03:00
|
|
|
title="Activity context prompt",
|
|
|
|
|
description="Custom prompt describing what is and is not suspicious activity to provide context for GenAI summaries.",
|
2025-10-01 02:07:16 +03:00
|
|
|
)
|
2025-08-10 14:57:54 +03:00
|
|
|
|
|
|
|
|
|
2024-09-28 22:21:42 +03:00
|
|
|
class ReviewConfig(FrigateBaseModel):
|
|
|
|
|
alerts: AlertsConfig = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default_factory=AlertsConfig,
|
|
|
|
|
title="Alerts config",
|
|
|
|
|
description="Settings for which tracked objects generate alerts and how alerts are retained.",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
|
|
|
|
detections: DetectionsConfig = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default_factory=DetectionsConfig,
|
|
|
|
|
title="Detections config",
|
|
|
|
|
description="Settings for creating detection events (non-alert) and how long to keep them.",
|
2024-09-28 22:21:42 +03:00
|
|
|
)
|
2025-08-10 14:57:54 +03:00
|
|
|
genai: GenAIReviewConfig = Field(
|
2026-02-27 18:55:36 +03:00
|
|
|
default_factory=GenAIReviewConfig,
|
|
|
|
|
title="GenAI config",
|
|
|
|
|
description="Controls use of generative AI for producing descriptions and summaries of review items.",
|
2025-08-10 14:57:54 +03:00
|
|
|
)
|