Improve review mqtt topic (#11072)

* Don't request preview for current hour and fix content type

* Send before / after on messages

* Send before / after for end

* Handle specific cases

* remove log

* Fix update type
This commit is contained in:
Nicolas Mowen 2024-04-22 20:20:30 -06:00 committed by GitHub
parent d6e93d039d
commit 2d71cd7fe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 70 additions and 16 deletions

View File

@ -1351,6 +1351,6 @@ def preview_thumbnail(file_name: str):
) )
response = make_response(jpg_bytes) response = make_response(jpg_bytes)
response.headers["Content-Type"] = "image/jpeg" response.headers["Content-Type"] = "image/webp"
response.headers["Cache-Control"] = "private, max-age=31536000" response.headers["Cache-Control"] = "private, max-age=31536000"
return response return response

View File

@ -146,25 +146,61 @@ class ReviewSegmentMaintainer(threading.Thread):
self.stop_event = stop_event self.stop_event = stop_event
def update_segment(self, segment: PendingReviewSegment) -> None: def new_segment(
"""Update segment.""" self,
seg_data = segment.get_data(ended=False) segment: PendingReviewSegment,
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data) ) -> None:
"""New segment."""
new_data = segment.get_data(ended=False)
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, new_data)
start_data = {k.name: v for k, v in new_data.items()}
self.requestor.send_data( self.requestor.send_data(
"reviews", "reviews",
json.dumps( json.dumps(
{"type": "update", "review": {k.name: v for k, v in seg_data.items()}} {
"type": "new",
"before": start_data,
"after": start_data,
}
),
)
def update_segment(
self,
segment: PendingReviewSegment,
camera_config: CameraConfig,
frame,
objects: list[TrackedObject],
) -> None:
"""Update segment."""
prev_data = segment.get_data(ended=False)
segment.update_frame(camera_config, frame, objects)
new_data = segment.get_data(ended=False)
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, new_data)
self.requestor.send_data(
"reviews",
json.dumps(
{
"type": "update",
"before": {k.name: v for k, v in prev_data.items()},
"after": {k.name: v for k, v in new_data.items()},
}
), ),
) )
def end_segment(self, segment: PendingReviewSegment) -> None: def end_segment(self, segment: PendingReviewSegment) -> None:
"""End segment.""" """End segment."""
seg_data = segment.get_data(ended=True) final_data = segment.get_data(ended=True)
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, seg_data) self.requestor.send_data(UPSERT_REVIEW_SEGMENT, final_data)
end_data = {k.name: v for k, v in final_data.items()}
self.requestor.send_data( self.requestor.send_data(
"reviews", "reviews",
json.dumps( json.dumps(
{"type": "end", "review": {k.name: v for k, v in seg_data.items()}} {
"type": "end",
"before": end_data,
"after": end_data,
}
), ),
) )
self.active_review_segments[segment.camera] = None self.active_review_segments[segment.camera] = None
@ -219,9 +255,10 @@ class ReviewSegmentMaintainer(threading.Thread):
yuv_frame = self.frame_manager.get( yuv_frame = self.frame_manager.get(
frame_id, camera_config.frame_shape_yuv frame_id, camera_config.frame_shape_yuv
) )
segment.update_frame(camera_config, yuv_frame, active_objects) self.update_segment(
segment, camera_config, yuv_frame, active_objects
)
self.frame_manager.close(frame_id) self.frame_manager.close(frame_id)
self.update_segment(segment)
except FileNotFoundError: except FileNotFoundError:
return return
else: else:
@ -317,7 +354,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]) self.new_segment(self.active_review_segments[camera])
except FileNotFoundError: except FileNotFoundError:
return return

View File

@ -12,6 +12,7 @@ import {
InProgressPreview, InProgressPreview,
VideoPreview, VideoPreview,
} from "../player/PreviewThumbnailPlayer"; } from "../player/PreviewThumbnailPlayer";
import { isCurrentHour } from "@/utils/dateUtil";
type AnimatedEventCardProps = { type AnimatedEventCardProps = {
event: ReviewSegment; event: ReviewSegment;
@ -19,10 +20,14 @@ type AnimatedEventCardProps = {
export function AnimatedEventCard({ event }: AnimatedEventCardProps) { export function AnimatedEventCard({ event }: AnimatedEventCardProps) {
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
const currentHour = useMemo(() => isCurrentHour(event.start_time), [event]);
// preview // preview
const { data: previews } = useSWR<Preview[]>( const { data: previews } = useSWR<Preview[]>(
`/preview/${event.camera}/start/${Math.round(event.start_time)}/end/${Math.round(event.end_time || event.start_time + 20)}`, currentHour
? null
: `/preview/${event.camera}/start/${Math.round(event.start_time)}/end/${Math.round(event.end_time || event.start_time + 20)}`,
); );
// interaction // interaction

View File

@ -31,7 +31,8 @@ type FrigateObjectState = {
export interface FrigateReview { export interface FrigateReview {
type: "new" | "update" | "end"; type: "new" | "update" | "end";
review: ReviewSegment; before: ReviewSegment;
after: ReviewSegment;
} }
export interface FrigateEvent { export interface FrigateEvent {

View File

@ -47,8 +47,19 @@ export default function LiveDashboardView({
} }
// if event is ended and was saved, update events list // if event is ended and was saved, update events list
if (eventUpdate.review.severity == "alert") { if (eventUpdate.after.severity == "alert") {
setTimeout(() => updateEvents(), eventUpdate.type == "end" ? 1000 : 6000); if (eventUpdate.type == "end" || eventUpdate.type == "new") {
setTimeout(
() => updateEvents(),
eventUpdate.type == "end" ? 1000 : 6000,
);
} else if (
eventUpdate.before.data.objects.length <
eventUpdate.after.data.objects.length
) {
setTimeout(() => updateEvents(), 5000);
}
return; return;
} }
}, [eventUpdate, updateEvents]); }, [eventUpdate, updateEvents]);