Update review maintainer to save events when ongoing

This commit is contained in:
Nicolas Mowen 2024-04-10 09:36:49 -06:00
parent 3d43c5e811
commit befc00d44a
2 changed files with 38 additions and 9 deletions

View File

@ -27,10 +27,18 @@ def review():
before = request.args.get("before", type=float, default=datetime.now().timestamp()) before = request.args.get("before", type=float, default=datetime.now().timestamp())
after = request.args.get( after = request.args.get(
"after", type=float, default=(datetime.now() - timedelta(hours=18)).timestamp() "after", type=float, default=(datetime.now() - timedelta(hours=24)).timestamp()
) )
clauses = [((ReviewSegment.start_time > after) & (ReviewSegment.end_time < before))] clauses = [
(
(ReviewSegment.start_time > after)
& (
(ReviewSegment.end_time.is_null(True))
| (ReviewSegment.end_time < before)
)
)
]
if cameras != "all": if cameras != "all":
camera_list = cameras.split(",") camera_list = cameras.split(",")
@ -45,6 +53,7 @@ def review():
for label in filtered_labels: for label in filtered_labels:
label_clauses.append( label_clauses.append(
(ReviewSegment.data["objects"].cast("text") % f'*"{label}"*') (ReviewSegment.data["objects"].cast("text") % f'*"{label}"*')
| ((ReviewSegment.data["audio"].cast("text") % f'*"{label}"*'))
) )
label_clause = reduce(operator.or_, label_clauses) label_clause = reduce(operator.or_, label_clauses)
@ -94,6 +103,7 @@ def review_summary():
for label in filtered_labels: for label in filtered_labels:
label_clauses.append( label_clauses.append(
(ReviewSegment.data["objects"].cast("text") % f'*"{label}"*') (ReviewSegment.data["objects"].cast("text") % f'*"{label}"*')
| ((ReviewSegment.data["audio"].cast("text") % f'*"{label}"*'))
) )
label_clause = reduce(operator.or_, label_clauses) label_clause = reduce(operator.or_, label_clauses)

View File

@ -66,6 +66,7 @@ class PendingReviewSegment:
# thumbnail # thumbnail
self.frame = np.zeros((THUMB_HEIGHT * 3 // 2, THUMB_WIDTH), np.uint8) self.frame = np.zeros((THUMB_HEIGHT * 3 // 2, THUMB_WIDTH), np.uint8)
self.frame_active_count = 0 self.frame_active_count = 0
self.frame_path = os.path.join(CLIPS_DIR, f"thumb-{self.camera}-{self.id}.jpg")
def update_frame( def update_frame(
self, camera_config: CameraConfig, frame, objects: list[TrackedObject] self, camera_config: CameraConfig, frame, objects: list[TrackedObject]
@ -98,19 +99,19 @@ class PendingReviewSegment:
color_frame, dsize=(width, THUMB_HEIGHT), interpolation=cv2.INTER_AREA color_frame, dsize=(width, THUMB_HEIGHT), interpolation=cv2.INTER_AREA
) )
def end(self) -> dict:
path = os.path.join(CLIPS_DIR, f"thumb-{self.camera}-{self.id}.jpg")
if self.frame is not None: if self.frame is not None:
cv2.imwrite(path, self.frame, [int(cv2.IMWRITE_WEBP_QUALITY), 60]) cv2.imwrite(
self.frame_path, self.frame, [int(cv2.IMWRITE_WEBP_QUALITY), 60]
)
def get_data(self, ended: bool) -> dict:
return { return {
ReviewSegment.id: self.id, ReviewSegment.id: self.id,
ReviewSegment.camera: self.camera, ReviewSegment.camera: self.camera,
ReviewSegment.start_time: self.start_time, ReviewSegment.start_time: self.start_time,
ReviewSegment.end_time: self.last_update, ReviewSegment.end_time: self.last_update if ended else None,
ReviewSegment.severity: self.severity.value, ReviewSegment.severity: self.severity.value,
ReviewSegment.thumb_path: path, ReviewSegment.thumb_path: self.frame_path,
ReviewSegment.data: { ReviewSegment.data: {
"detections": list(set(self.detections.keys())), "detections": list(set(self.detections.keys())),
"objects": list(set(self.detections.values())), "objects": list(set(self.detections.values())),
@ -141,9 +142,20 @@ class ReviewSegmentMaintainer(threading.Thread):
self.stop_event = stop_event self.stop_event = stop_event
def update_segment(self, segment: PendingReviewSegment) -> None:
"""Update segment."""
seg_data = segment.get_data(ended=False)
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data)
self.requestor.send_data(
"reviews",
json.dumps(
{"type": "update", "review": {k.name: v for k, v in seg_data.items()}}
),
)
def end_segment(self, segment: PendingReviewSegment) -> None: def end_segment(self, segment: PendingReviewSegment) -> None:
"""End segment.""" """End segment."""
seg_data = segment.end() seg_data = segment.get_data(ended=True)
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data) self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data)
self.requestor.send_data( self.requestor.send_data(
"reviews", "reviews",
@ -179,6 +191,7 @@ class ReviewSegmentMaintainer(threading.Thread):
) )
segment.update_frame(camera_config, yuv_frame, active_objects) segment.update_frame(camera_config, yuv_frame, active_objects)
self.frame_manager.close(frame_id) self.frame_manager.close(frame_id)
self.update_segment(segment)
for object in active_objects: for object in active_objects:
if not object["sub_label"]: if not object["sub_label"]:
@ -263,6 +276,7 @@ class ReviewSegmentMaintainer(threading.Thread):
camera_config, yuv_frame, active_objects camera_config, yuv_frame, active_objects
) )
self.frame_manager.close(frame_id) self.frame_manager.close(frame_id)
self.update_segment(self.active_review_segments[camera])
elif len(motion) >= 20: elif len(motion) >= 20:
self.active_review_segments[camera] = PendingReviewSegment( self.active_review_segments[camera] = PendingReviewSegment(
camera, camera,
@ -398,6 +412,11 @@ class ReviewSegmentMaintainer(threading.Thread):
"end_time" "end_time"
] ]
self.config_subscriber.stop()
self.requestor.stop()
self.detection_subscriber.stop()
logger.info("Exiting review maintainer...")
def get_active_objects( def get_active_objects(
frame_time: float, camera_config: CameraConfig, all_objects: list[TrackedObject] frame_time: float, camera_config: CameraConfig, all_objects: list[TrackedObject]