Convert config updating and video/audio queues to use zmq (#9893)

* Add config pub / sub pattern

* remove recording from feature metrics

* remove audio and feature metrics

* Check for updates from all cameras

* remove birdseye from camera metrics

* remove motion and detection camera metrics

* Ensure that all processes are stopped

* Stop communicators

* Detections

* Cleanup video output queue

* Use select for time sensitive polls

* Use ipc instead of tcp
This commit is contained in:
Nicolas Mowen
2024-02-19 07:26:59 -06:00
committed by GitHub
parent 3cff3a086b
commit dba21b606d
18 changed files with 394 additions and 336 deletions
+19 -12
View File
@@ -13,6 +13,8 @@ import numpy as np
import requests
from setproctitle import setproctitle
from frigate.comms.config_updater import ConfigSubscriber
from frigate.comms.detections_updater import DetectionPublisher, DetectionTypeEnum
from frigate.comms.inter_process import InterProcessRequestor
from frigate.config import CameraConfig, CameraInput, FfmpegConfig, FrigateConfig
from frigate.const import (
@@ -26,7 +28,7 @@ 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, FeatureMetricsTypes
from frigate.types import CameraMetricsTypes
from frigate.util.builtin import get_ffmpeg_arg_list
from frigate.util.services import listen
from frigate.video import start_or_restart_ffmpeg, stop_ffmpeg
@@ -67,9 +69,7 @@ def get_ffmpeg_command(ffmpeg: FfmpegConfig) -> list[str]:
def listen_to_audio(
config: FrigateConfig,
recordings_info_queue: mp.Queue,
camera_metrics: dict[str, CameraMetricsTypes],
process_info: dict[str, FeatureMetricsTypes],
) -> None:
stop_event = mp.Event()
audio_threads: list[threading.Thread] = []
@@ -95,9 +95,7 @@ def listen_to_audio(
if camera.enabled and camera.audio.enabled_in_config:
audio = AudioEventMaintainer(
camera,
recordings_info_queue,
camera_metrics,
process_info,
stop_event,
)
audio_threads.append(audio)
@@ -168,17 +166,13 @@ class AudioEventMaintainer(threading.Thread):
def __init__(
self,
camera: CameraConfig,
recordings_info_queue: mp.Queue,
camera_metrics: dict[str, CameraMetricsTypes],
feature_metrics: dict[str, FeatureMetricsTypes],
stop_event: mp.Event,
) -> None:
threading.Thread.__init__(self)
self.name = f"{camera.name}_audio_event_processor"
self.config = camera
self.recordings_info_queue = recordings_info_queue
self.camera_metrics = camera_metrics
self.feature_metrics = feature_metrics
self.detections: dict[dict[str, any]] = {}
self.stop_event = stop_event
self.detector = AudioTfl(stop_event, self.config.audio.num_threads)
@@ -191,9 +185,11 @@ class AudioEventMaintainer(threading.Thread):
# create communication for audio detections
self.requestor = InterProcessRequestor()
self.config_subscriber = ConfigSubscriber(f"config/audio/{camera.name}")
self.detection_publisher = DetectionPublisher(DetectionTypeEnum.audio)
def detect_audio(self, audio) -> None:
if not self.feature_metrics[self.config.name]["audio_enabled"].value:
if not self.config.audio.enabled or self.stop_event.is_set():
return
audio_as_float = audio.astype(np.float32)
@@ -221,8 +217,8 @@ class AudioEventMaintainer(threading.Thread):
self.handle_detection(label, score)
audio_detections.append(label)
# add audio info to recordings queue
self.recordings_info_queue.put(
# send audio detection data
self.detection_publisher.send_data(
(
self.config.name,
datetime.datetime.now().timestamp(),
@@ -339,8 +335,19 @@ class AudioEventMaintainer(threading.Thread):
self.start_or_restart_ffmpeg()
while not self.stop_event.is_set():
# check if there is an updated config
(
updated_topic,
updated_audio_config,
) = self.config_subscriber.check_for_update()
if updated_topic:
self.config.audio = updated_audio_config
self.read_audio()
stop_ffmpeg(self.audio_listener, self.logger)
self.logpipe.close()
self.requestor.stop()
self.config_subscriber.stop()
self.detection_publisher.stop()