mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-12 01:32:48 +03:00
Improve System Health pane (#24188)
* build out system health pane * tweaks * fixes * fix notice link so it opens the correct camera * tweak language
This commit is contained in:
committed by
Nicolas Mowen
parent
6d33b31bc6
commit
70ce193e09
@@ -60,6 +60,8 @@ from frigate.data_processing.real_time.license_plate import (
|
||||
)
|
||||
from frigate.data_processing.types import DataProcessorMetrics, PostProcessDataEnum
|
||||
from frigate.db.sqlitevecq import SqliteVecQueueDatabase
|
||||
from frigate.detectors.detection_runners import snapshot_loaded_devices
|
||||
from frigate.embeddings.types import fold_runtime_devices
|
||||
from frigate.events.types import (
|
||||
EventStateEnum,
|
||||
EventTypeEnum,
|
||||
@@ -101,6 +103,7 @@ class EmbeddingMaintainer(threading.Thread):
|
||||
super().__init__(name="embeddings_maintainer")
|
||||
self.config = config
|
||||
self.metrics = metrics
|
||||
self._published_devices: dict[str, str] = {}
|
||||
self.embeddings = None
|
||||
self.config_updater = CameraConfigUpdateSubscriber(
|
||||
self.config,
|
||||
@@ -337,6 +340,7 @@ class EmbeddingMaintainer(threading.Thread):
|
||||
self._expire_dedicated_lpr()
|
||||
self._process_finalized()
|
||||
self._process_event_metadata()
|
||||
self._publish_runtime_devices()
|
||||
|
||||
# Shutdown deferred processors
|
||||
for processor in self.realtime_processors:
|
||||
@@ -738,6 +742,19 @@ class EmbeddingMaintainer(threading.Thread):
|
||||
if isinstance(processor, ReviewDescriptionProcessor):
|
||||
processor.process_data(review_updates, PostProcessDataEnum.review)
|
||||
|
||||
def _publish_runtime_devices(self) -> None:
|
||||
"""Push each enrichment's loaded device to the shared metrics dict.
|
||||
|
||||
Runs every loop iteration, so only changed entries cross the manager
|
||||
boundary.
|
||||
"""
|
||||
for enrichment, device in fold_runtime_devices(
|
||||
snapshot_loaded_devices()
|
||||
).items():
|
||||
if self._published_devices.get(enrichment) != device:
|
||||
self.metrics.runtime_devices[enrichment] = device
|
||||
self._published_devices[enrichment] = device
|
||||
|
||||
def _process_event_metadata(self):
|
||||
# Check for regenerate description requests
|
||||
(topic, payload) = self.event_metadata_subscriber.check_for_update()
|
||||
|
||||
@@ -6,7 +6,10 @@ import os
|
||||
import numpy as np
|
||||
|
||||
from frigate.const import MODEL_CACHE_DIR
|
||||
from frigate.detectors.detection_runners import get_optimized_runner
|
||||
from frigate.detectors.detection_runners import (
|
||||
get_optimized_runner,
|
||||
record_loaded_device,
|
||||
)
|
||||
from frigate.embeddings.types import EnrichmentModelTypeEnum
|
||||
from frigate.log import suppress_stderr_during
|
||||
from frigate.util.downloader import ModelDownloader
|
||||
@@ -62,13 +65,18 @@ class FaceNetEmbedding(BaseEmbedding):
|
||||
if self.downloader:
|
||||
self.downloader.wait_for_download()
|
||||
|
||||
model_path = os.path.join(MODEL_CACHE_DIR, "facedet/facenet.tflite")
|
||||
|
||||
# Suppress TFLite delegate creation messages that bypass Python logging
|
||||
with suppress_stderr_during("tflite_interpreter_init"):
|
||||
self.runner = Interpreter(
|
||||
model_path=os.path.join(MODEL_CACHE_DIR, "facedet/facenet.tflite"),
|
||||
num_threads=2,
|
||||
)
|
||||
self.runner = Interpreter(model_path=model_path, num_threads=2)
|
||||
self.runner.allocate_tensors()
|
||||
|
||||
# tflite never goes through get_optimized_runner, so the small face
|
||||
# model would otherwise never report a device
|
||||
record_loaded_device(
|
||||
model_path, EnrichmentModelTypeEnum.facenet.value, "CPU"
|
||||
)
|
||||
self.tensor_input_details = self.runner.get_input_details()
|
||||
self.tensor_output_details = self.runner.get_output_details()
|
||||
|
||||
|
||||
@@ -13,3 +13,37 @@ class EnrichmentModelTypeEnum(str, Enum):
|
||||
jina_v2 = "jina_v2"
|
||||
paddleocr = "paddleocr"
|
||||
yolov9_license_plate = "yolov9_license_plate"
|
||||
|
||||
|
||||
# which enrichment each model type belongs to; the single place this lives
|
||||
ENRICHMENT_FOR_MODEL_TYPE: dict[str, str] = {
|
||||
EnrichmentModelTypeEnum.arcface.value: "face_recognition",
|
||||
EnrichmentModelTypeEnum.facenet.value: "face_recognition",
|
||||
EnrichmentModelTypeEnum.jina_v1.value: "semantic_search",
|
||||
EnrichmentModelTypeEnum.jina_v2.value: "semantic_search",
|
||||
EnrichmentModelTypeEnum.paddleocr.value: "lpr",
|
||||
EnrichmentModelTypeEnum.yolov9_license_plate.value: "lpr",
|
||||
}
|
||||
|
||||
|
||||
def fold_runtime_devices(loaded: dict[str, tuple[str, str]]) -> dict[str, str]:
|
||||
"""One device per enrichment from the per model registry.
|
||||
|
||||
A non CPU device wins so a model pinned to the CPU on purpose (the Jina V1
|
||||
text model) does not hide the accelerator its sibling loaded on, while an
|
||||
enrichment whose models all fell back to the CPU still reports CPU.
|
||||
"""
|
||||
folded: dict[str, str] = {}
|
||||
|
||||
for model_type, device in loaded.values():
|
||||
enrichment = ENRICHMENT_FOR_MODEL_TYPE.get(model_type)
|
||||
|
||||
if enrichment is None:
|
||||
continue
|
||||
|
||||
current = folded.get(enrichment)
|
||||
|
||||
if current is None or ("CPU" in current and "CPU" not in device):
|
||||
folded[enrichment] = device
|
||||
|
||||
return folded
|
||||
|
||||
Reference in New Issue
Block a user