mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-06-21 03:41:55 +03:00
Adds a per-camera ONVIF subscriber that lets cameras with native
hardware motion detection (e.g. OpenIPC firmware for HiSilicon,
Ingenic and SigmaStar SoCs; many ONVIF Profile-M devices) replace
Frigate's per-frame CPU motion analysis. Two standard ONVIF
transports are consumed in parallel:
- WS-BaseNotification PullPoint for the binary motion state
(tns1:RuleEngine/CellMotionDetector/Motion IsMotion=true|false,
with tns1:VideoSource/MotionAlarm State=true|false accepted as
a fallback for cameras that only publish the legacy topic).
- RTSP analytics metadata stream (application/vnd.onvif.metadata)
for the per-frame cell grid (tt:MotionInCells, base64 + PackBits
bit-packed bitmap). Cell layout is discovered once at startup via
AnalyticsService.GetAnalyticsModules and the camera's CellLayout
transformation is used to map cells to detect-frame pixel
rectangles via connected-components.
New config:
onvif.events.{enabled, subscription_timeout, use_metadata_stream}
motion.source: internal (default) | onvif
When motion.source: onvif, ImprovedMotionDetector is skipped and
motion_boxes come from the camera. Internal motion remains the
default; the new path is fully opt-in.
165 lines
5.9 KiB
Python
165 lines
5.9 KiB
Python
from enum import Enum
|
|
from typing import Optional, Union
|
|
|
|
from pydantic import Field, field_validator
|
|
|
|
from ..base import FrigateBaseModel
|
|
from ..env import EnvString
|
|
from .objects import DEFAULT_TRACKED_OBJECTS
|
|
|
|
__all__ = [
|
|
"OnvifConfig",
|
|
"OnvifEventsConfig",
|
|
"PtzAutotrackConfig",
|
|
"ZoomingModeEnum",
|
|
]
|
|
|
|
|
|
class ZoomingModeEnum(str, Enum):
|
|
disabled = "disabled"
|
|
absolute = "absolute"
|
|
relative = "relative"
|
|
|
|
|
|
class PtzAutotrackConfig(FrigateBaseModel):
|
|
enabled: bool = Field(
|
|
default=False,
|
|
title="Enable Autotracking",
|
|
description="Enable or disable automatic PTZ camera tracking of detected objects.",
|
|
)
|
|
calibrate_on_startup: bool = Field(
|
|
default=False,
|
|
title="Calibrate on start",
|
|
description="Measure PTZ motor speeds on startup to improve tracking accuracy. Frigate will update config with movement_weights after calibration.",
|
|
)
|
|
zooming: ZoomingModeEnum = Field(
|
|
default=ZoomingModeEnum.disabled,
|
|
title="Zoom mode",
|
|
description="Control zoom behavior: disabled (pan/tilt only), absolute (most compatible), or relative (concurrent pan/tilt/zoom).",
|
|
)
|
|
zoom_factor: float = Field(
|
|
default=0.3,
|
|
title="Zoom factor",
|
|
description="Control zoom level on tracked objects. Lower values keep more scene in view; higher values zoom in closer but may lose tracking. Values between 0.1 and 0.75.",
|
|
ge=0.1,
|
|
le=0.75,
|
|
)
|
|
track: list[str] = Field(
|
|
default=DEFAULT_TRACKED_OBJECTS,
|
|
title="Tracked objects",
|
|
description="List of object types that should trigger autotracking.",
|
|
)
|
|
required_zones: list[str] = Field(
|
|
default_factory=list,
|
|
title="Required zones",
|
|
description="Objects must enter one of these zones before autotracking begins.",
|
|
)
|
|
return_preset: str = Field(
|
|
default="home",
|
|
title="Return preset",
|
|
description="ONVIF preset name configured in camera firmware to return to after tracking ends.",
|
|
)
|
|
timeout: int = Field(
|
|
default=10,
|
|
title="Return timeout",
|
|
description="Wait this many seconds after losing tracking before returning camera to preset position.",
|
|
)
|
|
movement_weights: Optional[Union[str, list[str]]] = Field(
|
|
default_factory=list,
|
|
title="Movement weights",
|
|
description="Calibration values automatically generated by camera calibration. Do not modify manually.",
|
|
)
|
|
enabled_in_config: Optional[bool] = Field(
|
|
default=None,
|
|
title="Original autotrack state",
|
|
description="Internal field to track whether autotracking was enabled in configuration.",
|
|
)
|
|
|
|
@field_validator("movement_weights", mode="before")
|
|
@classmethod
|
|
def validate_weights(cls, v):
|
|
if v is None:
|
|
return None
|
|
|
|
if isinstance(v, str):
|
|
weights = list(map(str, map(float, v.split(","))))
|
|
elif isinstance(v, list):
|
|
weights = [str(float(val)) for val in v]
|
|
else:
|
|
raise ValueError("Invalid type for movement_weights")
|
|
|
|
if len(weights) != 6:
|
|
raise ValueError(
|
|
"movement_weights must have exactly 6 floats, remove this line from your config and run autotracking calibration"
|
|
)
|
|
|
|
return weights
|
|
|
|
|
|
class OnvifEventsConfig(FrigateBaseModel):
|
|
enabled: bool = Field(
|
|
default=False,
|
|
title="Enable ONVIF events",
|
|
description="Subscribe to the camera's ONVIF cell-motion notifications and use them as Frigate's motion signal.",
|
|
)
|
|
subscription_timeout: int = Field(
|
|
default=60,
|
|
ge=10,
|
|
le=600,
|
|
title="Subscription timeout",
|
|
description="Seconds before the PullPoint subscription expires and is renewed.",
|
|
)
|
|
use_metadata_stream: bool = Field(
|
|
default=True,
|
|
title="Use metadata stream",
|
|
description="Open the ONVIF analytics RTSP metadata stream to receive per-cell motion coordinates. Falls back to a full-frame box when disabled or when the camera does not advertise the track.",
|
|
)
|
|
|
|
|
|
class OnvifConfig(FrigateBaseModel):
|
|
host: EnvString = Field(
|
|
default="",
|
|
title="ONVIF host",
|
|
description="Host (and optional scheme) for the ONVIF service for this camera.",
|
|
)
|
|
port: int = Field(
|
|
default=8000,
|
|
title="ONVIF port",
|
|
description="Port number for the ONVIF service.",
|
|
)
|
|
user: Optional[EnvString] = Field(
|
|
default=None,
|
|
title="ONVIF username",
|
|
description="Username for ONVIF authentication; some devices require admin user for ONVIF.",
|
|
)
|
|
password: Optional[EnvString] = Field(
|
|
default=None,
|
|
title="ONVIF password",
|
|
description="Password for ONVIF authentication.",
|
|
)
|
|
tls_insecure: bool = Field(
|
|
default=False,
|
|
title="Disable TLS verify",
|
|
description="Skip TLS verification and disable digest auth for ONVIF (unsafe; use in safe networks only).",
|
|
)
|
|
profile: Optional[str] = Field(
|
|
default=None,
|
|
title="ONVIF profile",
|
|
description="Specific ONVIF media profile to use for PTZ control, matched by token or name. If not set, the first profile with valid PTZ configuration is selected automatically.",
|
|
)
|
|
autotracking: PtzAutotrackConfig = Field(
|
|
default_factory=PtzAutotrackConfig,
|
|
title="Autotracking",
|
|
description="Automatically track moving objects and keep them centered in the frame using PTZ camera movements.",
|
|
)
|
|
events: OnvifEventsConfig = Field(
|
|
default_factory=OnvifEventsConfig,
|
|
title="ONVIF events",
|
|
description="Consume camera-side ONVIF motion notifications instead of Frigate's CPU motion detector.",
|
|
)
|
|
ignore_time_mismatch: bool = Field(
|
|
default=False,
|
|
title="Ignore time mismatch",
|
|
description="Ignore time synchronization differences between camera and Frigate server for ONVIF communication.",
|
|
)
|