Compare commits

..

No commits in common. "d3469a5c157befd755277116387e091274cd00b1" and "ce40c7912f04d7daad61df029cfc3ea8eb0d8e98" have entirely different histories.

5 changed files with 46 additions and 78 deletions

View File

@ -131,9 +131,8 @@ class AudioTranscriptionPostProcessor(PostProcessorApi):
}, },
) )
# Embed the description if semantic search is enabled # Embed the description
if self.config.semantic_search.enabled: self.embeddings.embed_description(event_id, transcription)
self.embeddings.embed_description(event_id, transcription)
except DoesNotExist: except DoesNotExist:
logger.debug("No recording found for audio transcription post-processing") logger.debug("No recording found for audio transcription post-processing")

View File

@ -46,7 +46,7 @@ def should_update_state(prev_event: Event, current_event: Event) -> bool:
if prev_event["sub_label"] != current_event["sub_label"]: if prev_event["sub_label"] != current_event["sub_label"]:
return True return True
if set(prev_event["current_zones"]) != set(current_event["current_zones"]): if len(prev_event["current_zones"]) < len(current_event["current_zones"]):
return True return True
return False return False

View File

@ -86,11 +86,11 @@ class TimelineProcessor(threading.Thread):
event_data: dict[Any, Any], event_data: dict[Any, Any],
) -> bool: ) -> bool:
"""Handle object detection.""" """Handle object detection."""
save = False
camera_config = self.config.cameras[camera] camera_config = self.config.cameras[camera]
event_id = event_data["id"] event_id = event_data["id"]
# Base timeline entry data that all entries will share timeline_entry = {
base_entry = {
Timeline.timestamp: event_data["frame_time"], Timeline.timestamp: event_data["frame_time"],
Timeline.camera: camera, Timeline.camera: camera,
Timeline.source: "tracked_object", Timeline.source: "tracked_object",
@ -123,64 +123,40 @@ class TimelineProcessor(threading.Thread):
e[Timeline.data]["sub_label"] = event_data["sub_label"] e[Timeline.data]["sub_label"] = event_data["sub_label"]
if event_type == EventStateEnum.start: if event_type == EventStateEnum.start:
timeline_entry = base_entry.copy()
timeline_entry[Timeline.class_type] = "visible" timeline_entry[Timeline.class_type] = "visible"
self.insert_or_save(timeline_entry, prev_event_data, event_data) save = True
elif event_type == EventStateEnum.update: elif event_type == EventStateEnum.update:
# Check all conditions and create timeline entries for each change
entries_to_save = []
# Check for zone changes
prev_zones = set(prev_event_data["current_zones"])
current_zones = set(event_data["current_zones"])
zones_changed = prev_zones != current_zones
# Only save "entered_zone" events when the object is actually IN zones
if ( if (
zones_changed len(prev_event_data["current_zones"]) < len(event_data["current_zones"])
and not event_data["stationary"] and not event_data["stationary"]
and len(current_zones) > 0
): ):
zone_entry = base_entry.copy() timeline_entry[Timeline.class_type] = "entered_zone"
zone_entry[Timeline.class_type] = "entered_zone" timeline_entry[Timeline.data]["zones"] = event_data["current_zones"]
zone_entry[Timeline.data] = base_entry[Timeline.data].copy() save = True
zone_entry[Timeline.data]["zones"] = event_data["current_zones"] elif prev_event_data["stationary"] != event_data["stationary"]:
entries_to_save.append(zone_entry) timeline_entry[Timeline.class_type] = (
# Check for stationary status change
if prev_event_data["stationary"] != event_data["stationary"]:
stationary_entry = base_entry.copy()
stationary_entry[Timeline.class_type] = (
"stationary" if event_data["stationary"] else "active" "stationary" if event_data["stationary"] else "active"
) )
stationary_entry[Timeline.data] = base_entry[Timeline.data].copy() save = True
entries_to_save.append(stationary_entry) elif prev_event_data["attributes"] == {} and event_data["attributes"] != {}:
timeline_entry[Timeline.class_type] = "attribute"
# Check for new attributes timeline_entry[Timeline.data]["attribute"] = list(
if prev_event_data["attributes"] == {} and event_data["attributes"] != {}:
attribute_entry = base_entry.copy()
attribute_entry[Timeline.class_type] = "attribute"
attribute_entry[Timeline.data] = base_entry[Timeline.data].copy()
attribute_entry[Timeline.data]["attribute"] = list(
event_data["attributes"].keys() event_data["attributes"].keys()
)[0] )[0]
if len(event_data["current_attributes"]) > 0: if len(event_data["current_attributes"]) > 0:
attribute_entry[Timeline.data]["attribute_box"] = to_relative_box( timeline_entry[Timeline.data]["attribute_box"] = to_relative_box(
camera_config.detect.width, camera_config.detect.width,
camera_config.detect.height, camera_config.detect.height,
event_data["current_attributes"][0]["box"], event_data["current_attributes"][0]["box"],
) )
entries_to_save.append(attribute_entry) save = True
# Save all entries
for entry in entries_to_save:
self.insert_or_save(entry, prev_event_data, event_data)
elif event_type == EventStateEnum.end: elif event_type == EventStateEnum.end:
timeline_entry = base_entry.copy()
timeline_entry[Timeline.class_type] = "gone" timeline_entry[Timeline.class_type] = "gone"
save = True
if save:
self.insert_or_save(timeline_entry, prev_event_data, event_data) self.insert_or_save(timeline_entry, prev_event_data, event_data)
def handle_api_entry( def handle_api_entry(

View File

@ -233,7 +233,7 @@ export function GroupedClassificationCard({
}); });
if (!best) { if (!best) {
best = group.at(-1)!; return group.at(-1);
} }
const bestTyped: ClassificationItemData = best; const bestTyped: ClassificationItemData = best;
@ -377,34 +377,30 @@ export function GroupedClassificationCard({
)} )}
</ContentDescription> </ContentDescription>
</div> </div>
{classifiedEvent && ( {isDesktop && (
<div <div className="flex flex-row justify-between">
className={cn( {classifiedEvent && (
"flex", <Tooltip>
isDesktop && "flex-row justify-between", <TooltipTrigger asChild>
isMobile && "absolute right-4 top-8", <div
className="cursor-pointer"
tabIndex={-1}
onClick={() => {
navigate(`/explore?event_id=${classifiedEvent.id}`);
}}
>
<LuSearch className="size-4 text-secondary-foreground" />
</div>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
{t("details.item.button.viewInExplore", {
ns: "views/explore",
})}
</TooltipContent>
</TooltipPortal>
</Tooltip>
)} )}
>
<Tooltip>
<TooltipTrigger asChild>
<div
className="cursor-pointer"
tabIndex={-1}
onClick={() => {
navigate(`/explore?event_id=${classifiedEvent.id}`);
}}
>
<LuSearch className="size-4 text-secondary-foreground" />
</div>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
{t("details.item.button.viewInExplore", {
ns: "views/explore",
})}
</TooltipContent>
</TooltipPortal>
</Tooltip>
</div> </div>
)} )}
</Header> </Header>

View File

@ -309,10 +309,7 @@ export function RecordingView({
currentTimeRange.after <= currentTime && currentTimeRange.after <= currentTime &&
currentTimeRange.before >= currentTime currentTimeRange.before >= currentTime
) { ) {
mainControllerRef.current?.seekToTimestamp( mainControllerRef.current?.seekToTimestamp(currentTime, true);
currentTime,
mainControllerRef.current.isPlaying(),
);
} else { } else {
updateSelectedSegment(currentTime, true); updateSelectedSegment(currentTime, true);
} }