forked from Github/frigate
Support manual detections in review items (#10784)
* Only update frame time if it is older * Support manual detections as review items * Don't handle api detections in recordings * Store recordings for manual events
This commit is contained in:
@@ -5,6 +5,7 @@ import logging
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
import threading
|
||||
from enum import Enum
|
||||
from multiprocessing.synchronize import Event as MpEvent
|
||||
@@ -18,6 +19,7 @@ from frigate.comms.detections_updater import DetectionSubscriber, DetectionTypeE
|
||||
from frigate.comms.inter_process import InterProcessRequestor
|
||||
from frigate.config import CameraConfig, FrigateConfig
|
||||
from frigate.const import ALL_ATTRIBUTE_LABELS, CLIPS_DIR, UPSERT_REVIEW_SEGMENT
|
||||
from frigate.events.external import ManualEventState
|
||||
from frigate.models import ReviewSegment
|
||||
from frigate.object_processing import TrackedObject
|
||||
from frigate.util.image import SharedMemoryFrameManager, calculate_16_9_crop
|
||||
@@ -134,6 +136,9 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
self.config_subscriber = ConfigSubscriber("config/record/")
|
||||
self.detection_subscriber = DetectionSubscriber(DetectionTypeEnum.all)
|
||||
|
||||
# manual events
|
||||
self.indefinite_events: dict[str, dict[str, any]] = {}
|
||||
|
||||
self.stop_event = stop_event
|
||||
|
||||
def end_segment(self, segment: PendingReviewSegment) -> None:
|
||||
@@ -160,7 +165,8 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
active_objects = get_active_objects(frame_time, camera_config, objects)
|
||||
|
||||
if len(active_objects) > 0:
|
||||
segment.last_update = frame_time
|
||||
if frame_time > segment.last_update:
|
||||
segment.last_update = frame_time
|
||||
|
||||
# update type for this segment now that active objects are detected
|
||||
if segment.severity == SeverityEnum.signification_motion:
|
||||
@@ -198,7 +204,8 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
segment.severity == SeverityEnum.signification_motion
|
||||
and len(motion) >= THRESHOLD_MOTION_ACTIVITY
|
||||
):
|
||||
segment.last_update = frame_time
|
||||
if frame_time > segment.last_update:
|
||||
segment.last_update = frame_time
|
||||
else:
|
||||
if segment.severity == SeverityEnum.alert and frame_time > (
|
||||
segment.last_update + THRESHOLD_ALERT_ACTIVITY
|
||||
@@ -302,6 +309,15 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
dBFS,
|
||||
audio_detections,
|
||||
) = data
|
||||
elif topic == DetectionTypeEnum.api:
|
||||
(
|
||||
camera,
|
||||
frame_time,
|
||||
manual_info,
|
||||
) = data
|
||||
|
||||
if camera not in self.indefinite_events:
|
||||
self.indefinite_events[camera] = {}
|
||||
|
||||
if not self.config.cameras[camera].record.enabled:
|
||||
continue
|
||||
@@ -317,8 +333,31 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
motion_boxes,
|
||||
)
|
||||
elif topic == DetectionTypeEnum.audio and len(audio_detections) > 0:
|
||||
current_segment.last_update = frame_time
|
||||
if frame_time > current_segment.last_update:
|
||||
current_segment.last_update = frame_time
|
||||
|
||||
current_segment.audio.update(audio_detections)
|
||||
elif topic == DetectionTypeEnum.api:
|
||||
if manual_info["state"] == ManualEventState.complete:
|
||||
current_segment.detections[manual_info["event_id"]] = (
|
||||
manual_info["label"]
|
||||
)
|
||||
current_segment.severity = SeverityEnum.alert
|
||||
current_segment.last_update = manual_info["end_time"]
|
||||
elif manual_info["state"] == ManualEventState.start:
|
||||
self.indefinite_events[camera][manual_info["event_id"]] = (
|
||||
manual_info["label"]
|
||||
)
|
||||
current_segment.detections[manual_info["event_id"]] = (
|
||||
manual_info["label"]
|
||||
)
|
||||
current_segment.severity = SeverityEnum.alert
|
||||
|
||||
# temporarily make it so this event can not end
|
||||
current_segment.last_update = sys.maxsize
|
||||
elif manual_info["state"] == ManualEventState.end:
|
||||
self.indefinite_events[camera].pop(manual_info["event_id"])
|
||||
current_segment.last_update = manual_info["end_time"]
|
||||
else:
|
||||
if topic == DetectionTypeEnum.video:
|
||||
self.check_if_new_segment(
|
||||
@@ -337,6 +376,27 @@ class ReviewSegmentMaintainer(threading.Thread):
|
||||
set(audio_detections),
|
||||
[],
|
||||
)
|
||||
elif topic == DetectionTypeEnum.api:
|
||||
self.active_review_segments[camera] = PendingReviewSegment(
|
||||
camera,
|
||||
frame_time,
|
||||
SeverityEnum.alert,
|
||||
{manual_info["event_id"]: manual_info["label"]},
|
||||
set(),
|
||||
set(),
|
||||
[],
|
||||
)
|
||||
|
||||
if manual_info["state"] == ManualEventState.start:
|
||||
self.indefinite_events[camera][manual_info["event_id"]] = (
|
||||
manual_info["label"]
|
||||
)
|
||||
# temporarily make it so this event can not end
|
||||
self.active_review_segments[camera] = sys.maxsize
|
||||
elif manual_info["state"] == ManualEventState.complete:
|
||||
self.active_review_segments[camera].last_update = manual_info[
|
||||
"end_time"
|
||||
]
|
||||
|
||||
|
||||
def get_active_objects(
|
||||
|
||||
Reference in New Issue
Block a user