mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-31 10:50:32 +03:00
docstrings
This commit is contained in:
@@ -35,6 +35,7 @@ QUALITIES = frozenset(ConnectionQuality)
|
|||||||
|
|
||||||
|
|
||||||
def height_bucket(height: int) -> HeightBucket:
|
def height_bucket(height: int) -> HeightBucket:
|
||||||
|
"""The nearest standard resolution bucket for a detect height."""
|
||||||
for limit, bucket in HEIGHT_BUCKETS:
|
for limit, bucket in HEIGHT_BUCKETS:
|
||||||
if height <= limit:
|
if height <= limit:
|
||||||
return bucket
|
return bucket
|
||||||
@@ -43,6 +44,7 @@ def height_bucket(height: int) -> HeightBucket:
|
|||||||
|
|
||||||
|
|
||||||
def fps_bucket(fps: int) -> FpsBucket:
|
def fps_bucket(fps: int) -> FpsBucket:
|
||||||
|
"""The bucket for a detect fps."""
|
||||||
if fps <= 5:
|
if fps <= 5:
|
||||||
return FpsBucket.le_5
|
return FpsBucket.le_5
|
||||||
|
|
||||||
@@ -53,6 +55,7 @@ def fps_bucket(fps: int) -> FpsBucket:
|
|||||||
|
|
||||||
|
|
||||||
def retain_bucket(days: float) -> RetainBucket:
|
def retain_bucket(days: float) -> RetainBucket:
|
||||||
|
"""The bucket for a retention period in days."""
|
||||||
if days <= 0:
|
if days <= 0:
|
||||||
return RetainBucket.zero
|
return RetainBucket.zero
|
||||||
|
|
||||||
@@ -77,6 +80,7 @@ def preset_key(args: str | list[str], enum: Any) -> Any:
|
|||||||
|
|
||||||
|
|
||||||
def is_restream(path: str) -> bool:
|
def is_restream(path: str) -> bool:
|
||||||
|
"""Whether an input reads from the local go2rtc restream."""
|
||||||
try:
|
try:
|
||||||
url = urlsplit(path)
|
url = urlsplit(path)
|
||||||
return url.hostname in RESTREAM_HOSTS and url.port == RESTREAM_PORT
|
return url.hostname in RESTREAM_HOSTS and url.port == RESTREAM_PORT
|
||||||
@@ -85,11 +89,12 @@ def is_restream(path: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def role_input(camera: CameraConfig, role: CameraRoleEnum) -> CameraInput | None:
|
def role_input(camera: CameraConfig, role: CameraRoleEnum) -> CameraInput | None:
|
||||||
|
"""The camera's first input with the given role."""
|
||||||
return next((i for i in camera.ffmpeg.inputs if role in i.roles), None)
|
return next((i for i in camera.ffmpeg.inputs if role in i.roles), None)
|
||||||
|
|
||||||
|
|
||||||
def object_masks(camera: CameraConfig) -> int:
|
def object_masks(camera: CameraConfig) -> int:
|
||||||
# parsing copies camera-wide masks into every filter as global_<id>
|
"""Camera and per-label object masks, minus the global_<id> filter copies."""
|
||||||
own = sum(1 for mask in camera.objects.mask.values() if mask is not None)
|
own = sum(1 for mask in camera.objects.mask.values() if mask is not None)
|
||||||
per_label = sum(
|
per_label = sum(
|
||||||
1
|
1
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ def enrichment_device(label: object) -> EnrichmentDevice | None:
|
|||||||
|
|
||||||
|
|
||||||
def model_name(model: object) -> str | None:
|
def model_name(model: object) -> str | None:
|
||||||
|
"""The model's config value as a string."""
|
||||||
if model is None:
|
if model is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ def model_name(model: object) -> str | None:
|
|||||||
|
|
||||||
|
|
||||||
def semantic_model(model: object) -> SemanticSearchModel | None:
|
def semantic_model(model: object) -> SemanticSearchModel | None:
|
||||||
# any string that isn't a built-in model names a GenAI provider
|
"""A built-in Jina model, or genai for any GenAI provider name."""
|
||||||
name = model_name(model)
|
name = model_name(model)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
@@ -70,6 +71,7 @@ def semantic_model(model: object) -> SemanticSearchModel | None:
|
|||||||
|
|
||||||
|
|
||||||
def transcription_model(model: object) -> TranscriptionModel | None:
|
def transcription_model(model: object) -> TranscriptionModel | None:
|
||||||
|
"""Whisper, or genai for any GenAI provider name."""
|
||||||
name = model_name(model)
|
name = model_name(model)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
@@ -79,6 +81,7 @@ def transcription_model(model: object) -> TranscriptionModel | None:
|
|||||||
|
|
||||||
|
|
||||||
def users() -> dict[UserRole, int]:
|
def users() -> dict[UserRole, int]:
|
||||||
|
"""Count users by role, with any custom role counted as custom."""
|
||||||
roles: Counter[UserRole] = Counter(
|
roles: Counter[UserRole] = Counter(
|
||||||
closed(UserRole, user.role, UserRole.custom) for user in User.select(User.role)
|
closed(UserRole, user.role, UserRole.custom) for user in User.select(User.role)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ def cpu_model() -> str:
|
|||||||
|
|
||||||
|
|
||||||
def gpus(stats: dict[str, Any]) -> list[GpuInfo]:
|
def gpus(stats: dict[str, Any]) -> list[GpuInfo]:
|
||||||
|
"""GPUs with a stats entry, by vendor and capped name."""
|
||||||
found: list[GpuInfo] = []
|
found: list[GpuInfo] = []
|
||||||
|
|
||||||
for name, entry in stats.get("gpu_usages", {}).items():
|
for name, entry in stats.get("gpu_usages", {}).items():
|
||||||
@@ -64,6 +65,7 @@ def gpus(stats: dict[str, Any]) -> list[GpuInfo]:
|
|||||||
|
|
||||||
|
|
||||||
def decode_families() -> list[DecodeFamily]:
|
def decode_families() -> list[DecodeFamily]:
|
||||||
|
"""Hardware decode families the host supports."""
|
||||||
_, available = hwaccel_options()
|
_, available = hwaccel_options()
|
||||||
families = [
|
families = [
|
||||||
closed(DecodeFamily, family.key, DecodeFamily.other) for family in available
|
closed(DecodeFamily, family.key, DecodeFamily.other) for family in available
|
||||||
@@ -72,6 +74,7 @@ def decode_families() -> list[DecodeFamily]:
|
|||||||
|
|
||||||
|
|
||||||
def detection_hardware() -> dict[HardwareKey, int]:
|
def detection_hardware() -> dict[HardwareKey, int]:
|
||||||
|
"""Detection accelerators found by the hardware probe, by unit count."""
|
||||||
units: Counter[HardwareKey] = Counter()
|
units: Counter[HardwareKey] = Counter()
|
||||||
|
|
||||||
for found in hardware_prober.probe():
|
for found in hardware_prober.probe():
|
||||||
@@ -81,7 +84,10 @@ def detection_hardware() -> dict[HardwareKey, int]:
|
|||||||
|
|
||||||
|
|
||||||
def storage(stats: dict[str, Any]) -> StorageInfo:
|
def storage(stats: dict[str, Any]) -> StorageInfo:
|
||||||
# stats report sizes in MB
|
"""Filesystem, size, and usage of the recordings volume.
|
||||||
|
|
||||||
|
Stats report sizes in MB.
|
||||||
|
"""
|
||||||
entry = stats.get("service", {}).get("storage", {}).get(RECORD_DIR) or {}
|
entry = stats.get("service", {}).get("storage", {}).get(RECORD_DIR) or {}
|
||||||
total_mb = float(entry.get("total") or 0)
|
total_mb = float(entry.get("total") or 0)
|
||||||
used_mb = float(entry.get("used") or 0)
|
used_mb = float(entry.get("used") or 0)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ def image_variant(value: str | None) -> ImageVariant:
|
|||||||
|
|
||||||
|
|
||||||
def install_type() -> InstallType:
|
def install_type() -> InstallType:
|
||||||
# the add-on is a container too, so it has to be checked first
|
"""How Frigate runs; the add-on is a container too, so it's checked first."""
|
||||||
if os.path.isfile("/data/options.json"):
|
if os.path.isfile("/data/options.json"):
|
||||||
return InstallType.ha_addon
|
return InstallType.ha_addon
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ def install_type() -> InstallType:
|
|||||||
|
|
||||||
|
|
||||||
def arch(machine: str) -> Arch:
|
def arch(machine: str) -> Arch:
|
||||||
|
"""The CPU architecture for a platform.machine() value."""
|
||||||
match machine.lower():
|
match machine.lower():
|
||||||
case "x86_64" | "amd64":
|
case "x86_64" | "amd64":
|
||||||
return Arch.x86_64
|
return Arch.x86_64
|
||||||
@@ -48,6 +49,7 @@ def arch(machine: str) -> Arch:
|
|||||||
|
|
||||||
|
|
||||||
def kernel(release: str) -> str:
|
def kernel(release: str) -> str:
|
||||||
|
"""The major.minor of a kernel release string, or unknown."""
|
||||||
match = KERNEL_PATTERN.match(release)
|
match = KERNEL_PATTERN.match(release)
|
||||||
return f"{match.group(1)}.{match.group(2)}" if match else "unknown"
|
return f"{match.group(1)}.{match.group(2)}" if match else "unknown"
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class AnalyticsReporter(threading.Thread):
|
|||||||
return INTERVAL_S + self.rng.uniform(-JITTER_S, JITTER_S)
|
return INTERVAL_S + self.rng.uniform(-JITTER_S, JITTER_S)
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
|
"""Tick every wake until stopped; a failed tick never ends the thread."""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
self.tick()
|
self.tick()
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ def metric(description: str, *, public: bool = True, **kwargs: Any) -> Any:
|
|||||||
|
|
||||||
|
|
||||||
def count(description: str) -> Any:
|
def count(description: str) -> Any:
|
||||||
|
"""Declare a non-negative count field."""
|
||||||
return metric(description, ge=0)
|
return metric(description, ge=0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ OUTPUT = Path(__file__).parent / "docs" / "static" / "frigate-analytics-schema.j
|
|||||||
|
|
||||||
|
|
||||||
def render() -> str:
|
def render() -> str:
|
||||||
|
"""The JSON Schema for the current report models."""
|
||||||
schema = AnalyticsReport.model_json_schema()
|
schema = AnalyticsReport.model_json_schema()
|
||||||
schema["$schema"] = "https://json-schema.org/draft/2020-12/schema"
|
schema["$schema"] = "https://json-schema.org/draft/2020-12/schema"
|
||||||
schema["$id"] = "https://docs.frigate.video/frigate-analytics-schema.json"
|
schema["$id"] = "https://docs.frigate.video/frigate-analytics-schema.json"
|
||||||
|
|||||||
Reference in New Issue
Block a user