diff --git a/frigate/app.py b/frigate/app.py index 740ff7612..06b30f388 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -395,7 +395,7 @@ class FrigateApp: audio_process = mp.Process( target=listen_to_audio, name=f"audio_capture", - args=(self.config, self.event_queue) + args=(self.config) ) audio_process.daemon = True audio_process.start() diff --git a/frigate/events/audio.py b/frigate/events/audio.py index 6d627fc5b..662a517c9 100644 --- a/frigate/events/audio.py +++ b/frigate/events/audio.py @@ -6,9 +6,9 @@ import multiprocessing as mp import numpy as np import os import random +import requests import signal import string -import subprocess as sp import threading from types import FrameType from typing import Optional @@ -17,7 +17,6 @@ from setproctitle import setproctitle from frigate.config import CameraConfig, FrigateConfig from frigate.const import ( - AUDIO_DETECTOR, AUDIO_DURATION, AUDIO_FORMAT, AUDIO_SAMPLE_RATE, @@ -42,7 +41,7 @@ FFMPEG_COMMAND = ( ) -def listen_to_audio(config: FrigateConfig, event_queue: mp.Queue) -> None: +def listen_to_audio(config: FrigateConfig) -> None: stop_event = mp.Event() def receiveSignal(signalNumber: int, frame: Optional[FrameType]) -> None: @@ -57,7 +56,7 @@ def listen_to_audio(config: FrigateConfig, event_queue: mp.Queue) -> None: for camera in config.cameras.values(): if camera.enabled and camera.audio.enabled: - AudioEventMaintainer(camera, event_queue, stop_event).start() + AudioEventMaintainer(camera, stop_event).start() class AudioTfl: @@ -116,13 +115,10 @@ class AudioTfl: class AudioEventMaintainer(threading.Thread): - def __init__( - self, camera: CameraConfig, event_queue: mp.Queue, stop_event: mp.Event - ) -> None: + def __init__(self, camera: CameraConfig, stop_event: mp.Event) -> None: threading.Thread.__init__(self) self.name = f"{camera.name}_audio_event_processor" self.config = camera - self.queue = event_queue self.detections: dict[dict[str, any]] = {} self.stop_event = stop_event self.detector = AudioTfl() @@ -161,35 +157,31 @@ class AudioEventMaintainer(threading.Thread): "last_detection" ] = datetime.datetime.now().timestamp() else: - now = datetime.datetime.now().timestamp() - rand_id = "".join( - random.choices(string.ascii_lowercase + string.digits, k=6) - ) - event_id = f"{now}-{rand_id}" - self.detections[label] = { - "id": event_id, - "label": label, - "camera": self.config.name, - "score": score, - "start_time": now - self.config.record.events.pre_capture, - "last_detection": now, - } - self.queue.put( - (EventTypeEnum.audio, "start", self.config.name, self.detections[label]) + resp = requests.post( + f"http://127.0.0.1:5000/api/events/{self.config.name}/{label}/create", + json={"duration": None}, ) + if resp.status_code == 200: + event_id = resp.json["event_id"] + self.detections[label] = { + "id": event_id, + "last_detection": datetime.datetime.now().timestamp(), + } + def expire_detections(self) -> None: now = datetime.datetime.now().timestamp() for detection in self.detections.values(): if now - detection["last_detection"] > self.config.audio.max_not_heard: - detection["end_time"] = ( - detection["last_detection"] + self.config.record.events.post_capture - ) - self.queue.put( - (EventTypeEnum.audio, "end", self.config.name, detection) - ) self.detections[detection["label"]] = None + requests.put( + f"http://127.0.0.1/api/events/{detection['event_id']}/end", + json={ + "end_time": detection["last_detection"] + + self.config.record.events.post_capture + }, + ) def restart_audio_pipe(self) -> None: try: diff --git a/frigate/events/external.py b/frigate/events/external.py index 5422de260..b47d6ba9a 100644 --- a/frigate/events/external.py +++ b/frigate/events/external.py @@ -67,11 +67,10 @@ class ExternalEventProcessor: return event_id - def finish_manual_event(self, event_id: str) -> None: + def finish_manual_event(self, event_id: str, end_time: float) -> None: """Finish external event with indeterminate duration.""" - now = datetime.datetime.now().timestamp() self.queue.put( - (EventTypeEnum.api, "end", None, {"id": event_id, "end_time": now}) + (EventTypeEnum.api, "end", None, {"id": event_id, "end_time": end_time}) ) def _write_images( diff --git a/frigate/events/maintainer.py b/frigate/events/maintainer.py index 7fdb67aef..138586545 100644 --- a/frigate/events/maintainer.py +++ b/frigate/events/maintainer.py @@ -17,7 +17,6 @@ logger = logging.getLogger(__name__) class EventTypeEnum(str, Enum): api = "api" - audio = "audio" tracked_object = "tracked_object" @@ -92,8 +91,6 @@ class EventProcessor(threading.Thread): continue self.handle_object_detection(event_type, camera, event_data) - elif source_type == EventTypeEnum.audio: - self.handle_audio_detection(event_type, event_data) elif source_type == EventTypeEnum.api: self.handle_external_detection(event_type, event_data) @@ -218,30 +215,6 @@ class EventProcessor(threading.Thread): del self.events_in_process[event_data["id"]] self.event_processed_queue.put((event_data["id"], camera)) - def handle_audio_detection(self, type: str, event_data: Event) -> None: - event = { - Event.id: event_data["id"], - Event.label: event_data["label"], - Event.score: event_data["score"], - Event.camera: event_data["camera"], - Event.start_time: event_data["start_time"], - Event.end_time: event_data.get("end_time"), - Event.thumbnail: "", - Event.has_clip: True, - Event.has_snapshot: True, - Event.zones: [], - Event.data: {}, - } - - ( - Event.insert(event) - .on_conflict( - conflict_target=[Event.id], - update=event, - ) - .execute() - ) - def handle_external_detection(self, type: str, event_data: Event) -> None: if type == "new": event = { @@ -257,20 +230,14 @@ class EventProcessor(threading.Thread): Event.zones: [], Event.data: {}, } + Event.insert(event).execute() elif type == "end": event = { Event.id: event_data["id"], Event.end_time: event_data["end_time"], } - try: - ( - Event.insert(event) - .on_conflict( - conflict_target=[Event.id], - update=event, - ) - .execute() - ) - except Exception: - logger.warning(f"Failed to update manual event: {event_data['id']}") + try: + Event.update(event).execute() + except Exception: + logger.warning(f"Failed to update manual event: {event_data['id']}") diff --git a/frigate/http.py b/frigate/http.py index b4813c1f2..127b5defe 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -890,8 +890,11 @@ def create_event(camera_name, label): @bp.route("/events//end", methods=["PUT"]) def end_event(event_id): + json: dict[str, any] = request.get_json(silent=True) or {} + try: - current_app.external_processor.finish_manual_event(event_id) + end_time = json.get("end_time", datetime.now().timestamp()) + current_app.external_processor.finish_manual_event(event_id, end_time) except Exception: return jsonify( {"success": False, "message": f"{event_id} must be set and valid."}, 404