Handle timeline queue from tracked object data

This commit is contained in:
Nick Mowen 2023-04-20 15:37:36 -06:00
parent 6b277c7689
commit 229d134cb4
3 changed files with 106 additions and 1 deletions

View File

@ -30,6 +30,7 @@ from frigate.plus import PlusApi
from frigate.record import RecordingCleanup, RecordingMaintainer
from frigate.stats import StatsEmitter, stats_init
from frigate.storage import StorageMaintainer
from frigate.timeline import TimelineProcessor
from frigate.version import VERSION
from frigate.video import capture_camera, track_camera
from frigate.watchdog import FrigateWatchdog
@ -135,6 +136,9 @@ class FrigateApp:
# Queue for recordings info
self.recordings_info_queue: Queue = mp.Queue()
# Queue for timeline events
self.timeline_queue: Queue = mp.Queue()
def init_database(self) -> None:
# Migrate DB location
old_db_path = os.path.join(CLIPS_DIR, "frigate.db")
@ -314,6 +318,10 @@ class FrigateApp:
self.storage_maintainer = StorageMaintainer(self.config, self.stop_event)
self.storage_maintainer.start()
def start_timeline_processor(self) -> None:
self.timeline_processor = TimelineProcessor(self.timeline_queue, self.stop_event)
self.timeline_processor.start()
def start_stats_emitter(self) -> None:
self.stats_emitter = StatsEmitter(
self.config,

View File

@ -36,7 +36,7 @@ class Timeline(Model): # type: ignore[misc]
timestamp = DateTimeField()
camera = CharField(index=True, max_length=20)
source = CharField(index=True, max_length=20) # ex: tracked object, audio, external
class_type = CharField(max_length=50) # ex: entered_front_yard, heard_dog_barking
class_type = CharField(max_length=50) # ex: entered_zone, audio_heard
data = JSONField() # ex: tracked object id, region, box, etc.

97
frigate/timeline.py Normal file
View File

@ -0,0 +1,97 @@
"""Record events for object, audio, etc. detections."""
import logging
import threading
import queue
from enum import Enum
from frigate.models import Timeline
from multiprocessing.queues import Queue
from multiprocessing.synchronize import Event as MpEvent
logger = logging.getLogger(__name__)
class InputTypeEnum(str, Enum):
# audio = "audio"
# external = "external"
tracked_object = "tracked_object"
class TimelineProcessor(threading.Thread):
"""Handle timeline queue and update DB."""
def __init__(self, queue: Queue, stop_event: MpEvent) -> None:
threading.Thread.__init__(self)
self.name = "timeline_processor"
self.queue = queue
self.stop_event = stop_event
def run(self) -> None:
while not self.stop_event.is_set():
try:
(
camera,
input_type,
event_type,
prev_event_data,
event_data,
) = self.queue.get(timeout=1)
except queue.Empty:
continue
if input_type == InputTypeEnum.object:
self.handle_object_detection(
camera, event_type, prev_event_data, event_data
)
def handle_object_detection(
self,
camera: str,
event_type: str,
prev_event_data: dict[any, any],
event_data: dict[any, any],
) -> None:
"""Handle object detection."""
if event_type == "start":
Timeline.insert(
timestamp=event_data["frame_time"],
camera=camera,
source="tracked_object",
class_type="visible",
data={
"event_id": event_data["id"],
"region": event_data["region"],
"box": event_data["box"],
},
)
elif (
event_type == "update"
and prev_event_data["current_zones"] != event_type["current_zones"]
):
Timeline.insert(
timestamp=event_data["frame_time"],
camera=camera,
source="tracked_object",
class_type="entered_zone",
data={
"event_id": event_data["id"],
"region": event_data["region"],
"box": event_data["box"],
"zones": event_data["current_zones"],
},
)
elif event_type == "end":
Timeline.insert(
timestamp=event_data["frame_time"],
camera=camera,
source="tracked_object",
class_type="gone",
data={
"event_id": event_data["id"],
"region": event_data["region"],
"box": event_data["box"],
},
)