mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-15 07:35:27 +03:00
Make camera_metrics into a class
This commit is contained in:
parent
30a3c6dc86
commit
618b9ef37b
@ -17,6 +17,7 @@ from playhouse.sqliteq import SqliteQueueDatabase
|
||||
import frigate.util as util
|
||||
from frigate.api.auth import hash_password
|
||||
from frigate.api.fastapi_app import create_fastapi_app
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.comms.config_updater import ConfigPublisher
|
||||
from frigate.comms.dispatcher import Communicator, Dispatcher
|
||||
from frigate.comms.event_metadata_updater import (
|
||||
@ -66,7 +67,7 @@ from frigate.stats.emitter import StatsEmitter
|
||||
from frigate.stats.util import stats_init
|
||||
from frigate.storage import StorageMaintainer
|
||||
from frigate.timeline import TimelineProcessor
|
||||
from frigate.types import CameraMetricsTypes, PTZMetricsTypes
|
||||
from frigate.types import PTZMetricsTypes
|
||||
from frigate.util.builtin import empty_and_close_queue
|
||||
from frigate.util.object import get_camera_regions_grid
|
||||
from frigate.version import VERSION
|
||||
@ -85,7 +86,7 @@ class FrigateApp:
|
||||
self.detection_out_events: dict[str, MpEvent] = {}
|
||||
self.detection_shms: list[mp.shared_memory.SharedMemory] = []
|
||||
self.log_queue: Queue = mp.Queue()
|
||||
self.camera_metrics: dict[str, CameraMetricsTypes] = {}
|
||||
self.camera_metrics: dict[str, CameraMetrics] = {}
|
||||
self.ptz_metrics: dict[str, PTZMetricsTypes] = {}
|
||||
self.processes: dict[str, int] = {}
|
||||
self.region_grids: dict[str, list[list[dict[str, int]]]] = {}
|
||||
@ -107,34 +108,9 @@ class FrigateApp:
|
||||
logger.debug(f"Skipping directory: {d}")
|
||||
|
||||
def init_camera_metrics(self) -> None:
|
||||
for camera_name in self.config.cameras.keys():
|
||||
# create camera_metrics
|
||||
self.camera_metrics[camera_name] = {
|
||||
"camera_fps": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"skipped_fps": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"process_fps": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
"detection_fps": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"detection_frame": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"read_start": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"ffmpeg_pid": mp.Value("i", 0), # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
# from mypy 0.981 onwards
|
||||
"frame_queue": mp.Queue(maxsize=2),
|
||||
"capture_process": None,
|
||||
"process": None,
|
||||
"audio_rms": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
"audio_dBFS": mp.Value("d", 0.0), # type: ignore[typeddict-item]
|
||||
}
|
||||
for camera_name in self.config.cameras.keys():
|
||||
self.camera_metrics[camera_name] = CameraMetrics()
|
||||
self.ptz_metrics[camera_name] = {
|
||||
"ptz_autotracker_enabled": mp.Value( # type: ignore[typeddict-item]
|
||||
# issue https://github.com/python/typeshed/issues/8799
|
||||
@ -469,7 +445,7 @@ class FrigateApp:
|
||||
),
|
||||
daemon=True,
|
||||
)
|
||||
self.camera_metrics[name]["process"] = camera_process
|
||||
self.camera_metrics[name].process = camera_process
|
||||
camera_process.start()
|
||||
logger.info(f"Camera processor started for {name}: {camera_process.pid}")
|
||||
|
||||
@ -485,7 +461,7 @@ class FrigateApp:
|
||||
args=(name, config, self.shm_frame_count(), self.camera_metrics[name]),
|
||||
)
|
||||
capture_process.daemon = True
|
||||
self.camera_metrics[name]["capture_process"] = capture_process
|
||||
self.camera_metrics[name].capture_process = capture_process
|
||||
capture_process.start()
|
||||
logger.info(f"Capture process started for {name}: {capture_process.pid}")
|
||||
|
||||
@ -680,23 +656,22 @@ class FrigateApp:
|
||||
self.audio_process.join()
|
||||
|
||||
# ensure the capture processes are done
|
||||
for camera in self.camera_metrics.keys():
|
||||
capture_process = self.camera_metrics[camera]["capture_process"]
|
||||
for camera, metrics in self.camera_metrics.items():
|
||||
capture_process = metrics.capture_process
|
||||
if capture_process is not None:
|
||||
logger.info(f"Waiting for capture process for {camera} to stop")
|
||||
capture_process.terminate()
|
||||
capture_process.join()
|
||||
|
||||
# ensure the camera processors are done
|
||||
for camera in self.camera_metrics.keys():
|
||||
camera_process = self.camera_metrics[camera]["process"]
|
||||
for camera, metrics in self.camera_metrics.items():
|
||||
camera_process = metrics.process
|
||||
if camera_process is not None:
|
||||
logger.info(f"Waiting for process for {camera} to stop")
|
||||
camera_process.terminate()
|
||||
camera_process.join()
|
||||
logger.info(f"Closing frame queue for {camera}")
|
||||
frame_queue = self.camera_metrics[camera]["frame_queue"]
|
||||
empty_and_close_queue(frame_queue)
|
||||
empty_and_close_queue(metrics.frame_queue)
|
||||
|
||||
# ensure the detectors are done
|
||||
for detector in self.detectors.values():
|
||||
|
||||
38
frigate/camera/__init__.py
Normal file
38
frigate/camera/__init__.py
Normal file
@ -0,0 +1,38 @@
|
||||
import multiprocessing as mp
|
||||
from multiprocessing.sharedctypes import Synchronized
|
||||
from multiprocessing.synchronize import Event
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class CameraMetrics:
|
||||
camera_fps: Synchronized
|
||||
detection_fps: Synchronized
|
||||
detection_frame: Synchronized
|
||||
process_fps: Synchronized
|
||||
skipped_fps: Synchronized
|
||||
read_start: Synchronized
|
||||
audio_rms: Synchronized
|
||||
audio_dBFS: Synchronized
|
||||
|
||||
frame_queue: mp.Queue
|
||||
|
||||
process: Optional[mp.Process]
|
||||
capture_process: Optional[mp.Process]
|
||||
ffmpeg_pid: Synchronized
|
||||
|
||||
def __init__(self):
|
||||
self.camera_fps = mp.Value("d", 0)
|
||||
self.detection_fps = mp.Value("d", 0)
|
||||
self.detection_frame = mp.Value("d", 0)
|
||||
self.process_fps = mp.Value("d", 0)
|
||||
self.skipped_fps = mp.Value("d", 0)
|
||||
self.read_start = mp.Value("d", 0)
|
||||
self.audio_rms = mp.Value("d", 0)
|
||||
self.audio_dBFS = mp.Value("d", 0)
|
||||
|
||||
self.frame_queue = mp.Queue(maxsize=2)
|
||||
|
||||
self.process = None
|
||||
self.capture_process = None
|
||||
self.ffmpeg_pid = mp.Value("i", 0)
|
||||
|
||||
@ -12,6 +12,7 @@ import numpy as np
|
||||
import requests
|
||||
|
||||
import frigate.util as util
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.comms.config_updater import ConfigSubscriber
|
||||
from frigate.comms.detections_updater import DetectionPublisher, DetectionTypeEnum
|
||||
from frigate.comms.inter_process import InterProcessRequestor
|
||||
@ -27,7 +28,6 @@ from frigate.const import (
|
||||
from frigate.ffmpeg_presets import parse_preset_input
|
||||
from frigate.log import LogPipe
|
||||
from frigate.object_detection import load_labels
|
||||
from frigate.types import CameraMetricsTypes
|
||||
from frigate.util.builtin import get_ffmpeg_arg_list
|
||||
from frigate.video import start_or_restart_ffmpeg, stop_ffmpeg
|
||||
|
||||
@ -69,7 +69,7 @@ class AudioProcessor(util.Process):
|
||||
def __init__(
|
||||
self,
|
||||
config: FrigateConfig,
|
||||
camera_metrics: dict[str, CameraMetricsTypes],
|
||||
camera_metrics: dict[str, CameraMetrics],
|
||||
):
|
||||
super().__init__(name="frigate.audio_manager", daemon=True)
|
||||
|
||||
@ -123,7 +123,7 @@ class AudioEventMaintainer(threading.Thread):
|
||||
def __init__(
|
||||
self,
|
||||
camera: CameraConfig,
|
||||
camera_metrics: dict[str, CameraMetricsTypes],
|
||||
camera_metrics: dict[str, CameraMetrics],
|
||||
stop_event: threading.Event,
|
||||
) -> None:
|
||||
super().__init__(name=f"{camera.name}_audio_event_processor")
|
||||
@ -152,8 +152,8 @@ class AudioEventMaintainer(threading.Thread):
|
||||
audio_as_float = audio.astype(np.float32)
|
||||
rms, dBFS = self.calculate_audio_levels(audio_as_float)
|
||||
|
||||
self.camera_metrics[self.config.name]["audio_rms"].value = rms
|
||||
self.camera_metrics[self.config.name]["audio_dBFS"].value = dBFS
|
||||
self.camera_metrics[self.config.name].audio_rms.value = rms
|
||||
self.camera_metrics[self.config.name].audio_dBFS.value = dBFS
|
||||
|
||||
# only run audio detection when volume is above min_volume
|
||||
if rms >= self.config.audio.min_volume:
|
||||
|
||||
@ -11,10 +11,11 @@ import psutil
|
||||
import requests
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.const import CACHE_DIR, CLIPS_DIR, RECORD_DIR
|
||||
from frigate.object_detection import ObjectDetectProcess
|
||||
from frigate.types import CameraMetricsTypes, StatsTrackingTypes
|
||||
from frigate.types import StatsTrackingTypes
|
||||
from frigate.util.services import (
|
||||
get_amd_gpu_stats,
|
||||
get_bandwidth_stats,
|
||||
@ -49,7 +50,7 @@ def get_latest_version(config: FrigateConfig) -> str:
|
||||
|
||||
def stats_init(
|
||||
config: FrigateConfig,
|
||||
camera_metrics: dict[str, CameraMetricsTypes],
|
||||
camera_metrics: dict[str, CameraMetrics],
|
||||
detectors: dict[str, ObjectDetectProcess],
|
||||
processes: dict[str, int],
|
||||
) -> StatsTrackingTypes:
|
||||
@ -245,27 +246,23 @@ def stats_snapshot(
|
||||
|
||||
stats["cameras"] = {}
|
||||
for name, camera_stats in camera_metrics.items():
|
||||
total_detection_fps += camera_stats["detection_fps"].value
|
||||
pid = camera_stats["process"].pid if camera_stats["process"] else None
|
||||
ffmpeg_pid = (
|
||||
camera_stats["ffmpeg_pid"].value if camera_stats["ffmpeg_pid"] else None
|
||||
)
|
||||
total_detection_fps += camera_stats.detection_fps.value
|
||||
pid = camera_stats.process.pid if camera_stats.process else None
|
||||
ffmpeg_pid = camera_stats.ffmpeg_pid.value if camera_stats.ffmpeg_pid else None
|
||||
capture_pid = (
|
||||
camera_stats["capture_process"].pid
|
||||
if camera_stats["capture_process"]
|
||||
else None
|
||||
camera_stats.capture_process.pid if camera_stats.capture_process else None
|
||||
)
|
||||
stats["cameras"][name] = {
|
||||
"camera_fps": round(camera_stats["camera_fps"].value, 2),
|
||||
"process_fps": round(camera_stats["process_fps"].value, 2),
|
||||
"skipped_fps": round(camera_stats["skipped_fps"].value, 2),
|
||||
"detection_fps": round(camera_stats["detection_fps"].value, 2),
|
||||
"camera_fps": round(camera_stats.camera_fps.value, 2),
|
||||
"process_fps": round(camera_stats.process_fps.value, 2),
|
||||
"skipped_fps": round(camera_stats.skipped_fps.value, 2),
|
||||
"detection_fps": round(camera_stats.detection_fps.value, 2),
|
||||
"detection_enabled": config.cameras[name].detect.enabled,
|
||||
"pid": pid,
|
||||
"capture_pid": capture_pid,
|
||||
"ffmpeg_pid": ffmpeg_pid,
|
||||
"audio_rms": round(camera_stats["audio_rms"].value, 4),
|
||||
"audio_dBFS": round(camera_stats["audio_dBFS"].value, 4),
|
||||
"audio_rms": round(camera_stats.audio_rms.value, 4),
|
||||
"audio_dBFS": round(camera_stats.audio_dBFS.value, 4),
|
||||
}
|
||||
|
||||
stats["detectors"] = {}
|
||||
|
||||
@ -1,27 +1,11 @@
|
||||
from multiprocessing import Queue
|
||||
from multiprocessing.context import Process
|
||||
from multiprocessing.sharedctypes import Synchronized
|
||||
from multiprocessing.synchronize import Event
|
||||
from typing import Optional, TypedDict
|
||||
from typing import TypedDict
|
||||
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.object_detection import ObjectDetectProcess
|
||||
|
||||
|
||||
class CameraMetricsTypes(TypedDict):
|
||||
camera_fps: Synchronized
|
||||
capture_process: Optional[Process]
|
||||
detection_fps: Synchronized
|
||||
detection_frame: Synchronized
|
||||
ffmpeg_pid: Synchronized
|
||||
frame_queue: Queue
|
||||
process: Optional[Process]
|
||||
process_fps: Synchronized
|
||||
read_start: Synchronized
|
||||
skipped_fps: Synchronized
|
||||
audio_rms: Synchronized
|
||||
audio_dBFS: Synchronized
|
||||
|
||||
|
||||
class PTZMetricsTypes(TypedDict):
|
||||
ptz_autotracker_enabled: Synchronized
|
||||
ptz_tracking_active: Event
|
||||
@ -36,7 +20,7 @@ class PTZMetricsTypes(TypedDict):
|
||||
|
||||
|
||||
class StatsTrackingTypes(TypedDict):
|
||||
camera_metrics: dict[str, CameraMetricsTypes]
|
||||
camera_metrics: dict[str, CameraMetrics]
|
||||
detectors: dict[str, ObjectDetectProcess]
|
||||
started: int
|
||||
latest_frigate_version: str
|
||||
|
||||
@ -11,6 +11,7 @@ import time
|
||||
import cv2
|
||||
from setproctitle import setproctitle
|
||||
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.comms.config_updater import ConfigSubscriber
|
||||
from frigate.comms.inter_process import InterProcessRequestor
|
||||
from frigate.config import CameraConfig, DetectConfig, ModelConfig
|
||||
@ -386,7 +387,9 @@ class CameraCapture(threading.Thread):
|
||||
)
|
||||
|
||||
|
||||
def capture_camera(name, config: CameraConfig, shm_frame_count: int, process_info):
|
||||
def capture_camera(
|
||||
name, config: CameraConfig, shm_frame_count: int, camera_metrics: CameraMetrics
|
||||
):
|
||||
stop_event = mp.Event()
|
||||
|
||||
def receiveSignal(signalNumber, frame):
|
||||
@ -398,15 +401,14 @@ def capture_camera(name, config: CameraConfig, shm_frame_count: int, process_inf
|
||||
threading.current_thread().name = f"capture:{name}"
|
||||
setproctitle(f"frigate.capture:{name}")
|
||||
|
||||
frame_queue = process_info["frame_queue"]
|
||||
camera_watchdog = CameraWatchdog(
|
||||
name,
|
||||
config,
|
||||
shm_frame_count,
|
||||
frame_queue,
|
||||
process_info["camera_fps"],
|
||||
process_info["skipped_fps"],
|
||||
process_info["ffmpeg_pid"],
|
||||
camera_metrics.frame_queue,
|
||||
camera_metrics.camera_fps,
|
||||
camera_metrics.skipped_fps,
|
||||
camera_metrics.ffmpeg_pid,
|
||||
stop_event,
|
||||
)
|
||||
camera_watchdog.start()
|
||||
@ -421,7 +423,7 @@ def track_camera(
|
||||
detection_queue,
|
||||
result_connection,
|
||||
detected_objects_queue,
|
||||
process_info,
|
||||
camera_metrics: CameraMetrics,
|
||||
ptz_metrics,
|
||||
region_grid,
|
||||
):
|
||||
@ -437,7 +439,7 @@ def track_camera(
|
||||
setproctitle(f"frigate.process:{name}")
|
||||
listen()
|
||||
|
||||
frame_queue = process_info["frame_queue"]
|
||||
frame_queue = camera_metrics.frame_queue
|
||||
|
||||
frame_shape = config.frame_shape
|
||||
objects_to_track = config.objects.track
|
||||
@ -469,7 +471,7 @@ def track_camera(
|
||||
object_detector,
|
||||
object_tracker,
|
||||
detected_objects_queue,
|
||||
process_info,
|
||||
camera_metrics,
|
||||
objects_to_track,
|
||||
object_filters,
|
||||
stop_event,
|
||||
@ -542,7 +544,7 @@ def process_frames(
|
||||
object_detector: RemoteObjectDetector,
|
||||
object_tracker: ObjectTracker,
|
||||
detected_objects_queue: mp.Queue,
|
||||
process_info: dict,
|
||||
camera_metrics: CameraMetrics,
|
||||
objects_to_track: list[str],
|
||||
object_filters,
|
||||
stop_event,
|
||||
@ -550,9 +552,6 @@ def process_frames(
|
||||
region_grid,
|
||||
exit_on_empty: bool = False,
|
||||
):
|
||||
fps = process_info["process_fps"]
|
||||
detection_fps = process_info["detection_fps"]
|
||||
current_frame_time = process_info["detection_frame"]
|
||||
next_region_update = get_tomorrow_at_time(2)
|
||||
config_subscriber = ConfigSubscriber(f"config/detect/{camera_name}")
|
||||
|
||||
@ -589,7 +588,7 @@ def process_frames(
|
||||
break
|
||||
continue
|
||||
|
||||
current_frame_time.value = frame_time
|
||||
camera_metrics.detection_frame.value = frame_time
|
||||
ptz_metrics["ptz_frame_time"].value = frame_time
|
||||
|
||||
frame = frame_manager.get(
|
||||
@ -839,7 +838,7 @@ def process_frames(
|
||||
continue
|
||||
else:
|
||||
fps_tracker.update()
|
||||
fps.value = fps_tracker.eps()
|
||||
camera_metrics.process_fps.value = fps_tracker.eps()
|
||||
detected_objects_queue.put(
|
||||
(
|
||||
camera_name,
|
||||
@ -849,7 +848,7 @@ def process_frames(
|
||||
regions,
|
||||
)
|
||||
)
|
||||
detection_fps.value = object_detector.fps.eps()
|
||||
camera_metrics.detection_fps.value = object_detector.fps.eps()
|
||||
frame_manager.close(f"{camera_name}{frame_time}")
|
||||
|
||||
motion_detector.stop()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user