mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-09 04:35:25 +03:00
Support deleting review segments on recording cleanup
This commit is contained in:
parent
26f8552b1c
commit
2e9669fbc2
@ -9,7 +9,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from frigate.config import CameraConfig, FrigateConfig, RetainModeEnum
|
from frigate.config import CameraConfig, FrigateConfig, RetainModeEnum
|
||||||
from frigate.const import CACHE_DIR, RECORD_DIR
|
from frigate.const import CACHE_DIR, RECORD_DIR
|
||||||
from frigate.models import Event, Previews, Recordings
|
from frigate.models import Event, Previews, Recordings, ReviewSegment
|
||||||
from frigate.record.util import remove_empty_directories, sync_recordings
|
from frigate.record.util import remove_empty_directories, sync_recordings
|
||||||
from frigate.util.builtin import clear_and_unlink, get_tomorrow_at_time
|
from frigate.util.builtin import clear_and_unlink, get_tomorrow_at_time
|
||||||
|
|
||||||
@ -174,6 +174,65 @@ class RecordingCleanup(threading.Thread):
|
|||||||
Previews.id << deleted_previews_list[i : i + max_deletes]
|
Previews.id << deleted_previews_list[i : i + max_deletes]
|
||||||
).execute()
|
).execute()
|
||||||
|
|
||||||
|
review_segments: list[ReviewSegment] = (
|
||||||
|
ReviewSegment.select(
|
||||||
|
ReviewSegment.id,
|
||||||
|
ReviewSegment.start_time,
|
||||||
|
ReviewSegment.end_time,
|
||||||
|
ReviewSegment.thumb_path,
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
ReviewSegment.camera == config.name,
|
||||||
|
ReviewSegment.end_time < expire_date,
|
||||||
|
)
|
||||||
|
.order_by(ReviewSegment.start_time)
|
||||||
|
.namedtuples()
|
||||||
|
.iterator()
|
||||||
|
)
|
||||||
|
|
||||||
|
# expire review segments
|
||||||
|
recording_start = 0
|
||||||
|
deleted_segments = set()
|
||||||
|
for segment in review_segments:
|
||||||
|
keep = False
|
||||||
|
# look for a reason to keep this segment
|
||||||
|
for idx in range(recording_start, len(kept_recordings)):
|
||||||
|
start_time, end_time = kept_recordings[idx]
|
||||||
|
|
||||||
|
# if the recording starts in the future, stop checking recordings
|
||||||
|
# and let this segment expire
|
||||||
|
if start_time > segment.end_time:
|
||||||
|
keep = False
|
||||||
|
break
|
||||||
|
|
||||||
|
# if the recording ends after the segment starts, keep it
|
||||||
|
# and stop looking at recordings
|
||||||
|
if end_time >= segment.start_time:
|
||||||
|
keep = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# if the recording ends before this segment starts, skip
|
||||||
|
# this recording and check the next recording for an overlap.
|
||||||
|
# since the kept recordings and segments are sorted, we can skip recordings
|
||||||
|
# that end before the current segment started
|
||||||
|
if end_time < segment.start_time:
|
||||||
|
recording_start = idx
|
||||||
|
|
||||||
|
# Delete segments without any relevant recordings
|
||||||
|
if not keep:
|
||||||
|
Path(segment.thumb_path).unlink(missing_ok=True)
|
||||||
|
deleted_segments.add(segment.id)
|
||||||
|
|
||||||
|
# expire segments
|
||||||
|
logger.debug(f"Expiring {len(deleted_segments)} segments")
|
||||||
|
# delete up to 100,000 at a time
|
||||||
|
max_deletes = 100000
|
||||||
|
deleted_segments_list = list(deleted_segments)
|
||||||
|
for i in range(0, len(deleted_segments_list), max_deletes):
|
||||||
|
ReviewSegment.delete().where(
|
||||||
|
ReviewSegment.id << deleted_segments_list[i : i + max_deletes]
|
||||||
|
).execute()
|
||||||
|
|
||||||
def expire_recordings(self) -> None:
|
def expire_recordings(self) -> None:
|
||||||
"""Delete recordings based on retention config."""
|
"""Delete recordings based on retention config."""
|
||||||
logger.debug("Start expire recordings.")
|
logger.debug("Start expire recordings.")
|
||||||
|
|||||||
@ -185,7 +185,7 @@ class ReviewSegmentMaintainer(threading.Thread):
|
|||||||
camera_name = updated_topic.rpartition("/")[-1]
|
camera_name = updated_topic.rpartition("/")[-1]
|
||||||
self.config.cameras[camera_name].record = updated_record_config
|
self.config.cameras[camera_name].record = updated_record_config
|
||||||
|
|
||||||
(topic, data) = self.detection_subscriber.get_data()
|
(topic, data) = self.detection_subscriber.get_data(timeout=1)
|
||||||
|
|
||||||
if not topic:
|
if not topic:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user