Use api instead of event queue to save audio events

This commit is contained in:
Nick Mowen 2023-06-19 07:50:02 -06:00
parent f0a59da933
commit cc0cb3a78d
5 changed files with 33 additions and 72 deletions

View File

@ -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()

View File

@ -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:

View File

@ -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(

View File

@ -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']}")

View File

@ -890,8 +890,11 @@ def create_event(camera_name, label):
@bp.route("/events/<event_id>/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