mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Event cleanup (#11225)
* remove duplicate event purging * Slightly increase stationary object sensitivity * Add toast for export starting * Increase stationary threshold as well * Update message * Make text consistent * Update message
This commit is contained in:
parent
e7950abec3
commit
216e44bc34
@ -184,43 +184,6 @@ class EventCleanup(threading.Thread):
|
|||||||
Event.update(update_params).where(Event.id << events_to_update).execute()
|
Event.update(update_params).where(Event.id << events_to_update).execute()
|
||||||
return events_to_update
|
return events_to_update
|
||||||
|
|
||||||
def purge_duplicates(self) -> None:
|
|
||||||
duplicate_query = """with grouped_events as (
|
|
||||||
select id,
|
|
||||||
label,
|
|
||||||
camera,
|
|
||||||
has_snapshot,
|
|
||||||
has_clip,
|
|
||||||
end_time,
|
|
||||||
row_number() over (
|
|
||||||
partition by label, camera, round(start_time/5,0)*5
|
|
||||||
order by end_time-start_time desc
|
|
||||||
) as copy_number
|
|
||||||
from event
|
|
||||||
)
|
|
||||||
|
|
||||||
select distinct id, camera, has_snapshot, has_clip from grouped_events
|
|
||||||
where copy_number > 1 and end_time not null;"""
|
|
||||||
|
|
||||||
duplicate_events: list[Event] = Event.raw(duplicate_query)
|
|
||||||
for event in duplicate_events:
|
|
||||||
logger.debug(f"Removing duplicate: {event.id}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
media_name = f"{event.camera}-{event.id}"
|
|
||||||
media_path = Path(f"{os.path.join(CLIPS_DIR, media_name)}.jpg")
|
|
||||||
media_path.unlink(missing_ok=True)
|
|
||||||
media_path = Path(f"{os.path.join(CLIPS_DIR, media_name)}-clean.png")
|
|
||||||
media_path.unlink(missing_ok=True)
|
|
||||||
except OSError as e:
|
|
||||||
logger.warning(f"Unable to delete event images: {e}")
|
|
||||||
|
|
||||||
(
|
|
||||||
Event.delete()
|
|
||||||
.where(Event.id << [event.id for event in duplicate_events])
|
|
||||||
.execute()
|
|
||||||
)
|
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
# only expire events every 5 minutes
|
# only expire events every 5 minutes
|
||||||
while not self.stop_event.wait(300):
|
while not self.stop_event.wait(300):
|
||||||
@ -232,7 +195,6 @@ class EventCleanup(threading.Thread):
|
|||||||
).execute()
|
).execute()
|
||||||
|
|
||||||
self.expire(EventCleanupType.snapshots)
|
self.expire(EventCleanupType.snapshots)
|
||||||
self.purge_duplicates()
|
|
||||||
|
|
||||||
# drop events from db where has_clip and has_snapshot are false
|
# drop events from db where has_clip and has_snapshot are false
|
||||||
delete_query = Event.delete().where(
|
delete_query = Event.delete().where(
|
||||||
|
@ -22,8 +22,8 @@ from frigate.util.object import average_boxes, median_of_boxes
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
THRESHOLD_ACTIVE_IOU = 0.2
|
THRESHOLD_ACTIVE_IOU = 0.35
|
||||||
THRESHOLD_STATIONARY_IOU = 0.6
|
THRESHOLD_STATIONARY_IOU = 0.7
|
||||||
MAX_STATIONARY_HISTORY = 10
|
MAX_STATIONARY_HISTORY = 10
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,11 +186,11 @@ export default function HlsVideoPlayer({
|
|||||||
const resp = await onUploadFrame(videoRef.current.currentTime);
|
const resp = await onUploadFrame(videoRef.current.currentTime);
|
||||||
|
|
||||||
if (resp && resp.status == 200) {
|
if (resp && resp.status == 200) {
|
||||||
toast.success("Successfully submitted frame to Frigate Plus", {
|
toast.success("Successfully submitted frame to Frigate+", {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.success("Failed to submit frame to Frigate Plus", {
|
toast.success("Failed to submit frame to Frigate+", {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@ import { useCameraMotionNextTimestamp } from "@/hooks/use-camera-activity";
|
|||||||
import useOptimisticState from "@/hooks/use-optimistic-state";
|
import useOptimisticState from "@/hooks/use-optimistic-state";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import scrollIntoView from "scroll-into-view-if-needed";
|
import scrollIntoView from "scroll-into-view-if-needed";
|
||||||
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
type EventViewProps = {
|
type EventViewProps = {
|
||||||
reviews?: ReviewSegment[];
|
reviews?: ReviewSegment[];
|
||||||
@ -194,10 +196,31 @@ export default function EventView({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.post(
|
axios
|
||||||
`export/${review.camera}/start/${review.start_time}/end/${review.end_time}`,
|
.post(
|
||||||
{ playback: "realtime" },
|
`export/${review.camera}/start/${review.start_time}/end/${review.end_time}`,
|
||||||
);
|
{ playback: "realtime" },
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status == 200) {
|
||||||
|
toast.success(
|
||||||
|
"Successfully started export. View the file in the /exports folder.",
|
||||||
|
{ position: "top-center" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error.response?.data?.message) {
|
||||||
|
toast.error(
|
||||||
|
`Failed to start export: ${error.response.data.message}`,
|
||||||
|
{ position: "top-center" },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
toast.error(`Failed to start export: ${error.message}`, {
|
||||||
|
position: "top-center",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[reviewItems],
|
[reviewItems],
|
||||||
);
|
);
|
||||||
@ -215,6 +238,7 @@ export default function EventView({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="py-2 flex flex-col size-full">
|
<div className="py-2 flex flex-col size-full">
|
||||||
|
<Toaster />
|
||||||
<div className="h-11 mb-2 pl-3 pr-2 relative flex justify-between items-center">
|
<div className="h-11 mb-2 pl-3 pr-2 relative flex justify-between items-center">
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<Logo className="absolute inset-x-1/2 -translate-x-1/2 h-8" />
|
<Logo className="absolute inset-x-1/2 -translate-x-1/2 h-8" />
|
||||||
|
Loading…
Reference in New Issue
Block a user