mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-18 14:18:21 +03:00
Merge pull request #43 from ibs0d/codex/audit-preview-retention-logic
Fix preview media sync for per-camera recording roots
This commit is contained in:
commit
eb2a684de1
@ -6,9 +6,9 @@ from peewee_migrate import Router
|
|||||||
from playhouse.sqlite_ext import SqliteExtDatabase
|
from playhouse.sqlite_ext import SqliteExtDatabase
|
||||||
from playhouse.sqliteq import SqliteQueueDatabase
|
from playhouse.sqliteq import SqliteQueueDatabase
|
||||||
|
|
||||||
from frigate.models import Recordings, RecordingsToDelete
|
from frigate.models import Previews, Recordings, RecordingsToDelete
|
||||||
from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS
|
from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS
|
||||||
from frigate.util.media import sync_recordings
|
from frigate.util.media import sync_previews, sync_recordings
|
||||||
|
|
||||||
|
|
||||||
class TestMediaSync(unittest.TestCase):
|
class TestMediaSync(unittest.TestCase):
|
||||||
@ -19,7 +19,7 @@ class TestMediaSync(unittest.TestCase):
|
|||||||
migrate_db.close()
|
migrate_db.close()
|
||||||
|
|
||||||
self.db = SqliteQueueDatabase(TEST_DB)
|
self.db = SqliteQueueDatabase(TEST_DB)
|
||||||
models = [Recordings, RecordingsToDelete]
|
models = [Previews, Recordings, RecordingsToDelete]
|
||||||
self.db.bind(models)
|
self.db.bind(models)
|
||||||
|
|
||||||
self.root_a = tempfile.mkdtemp()
|
self.root_a = tempfile.mkdtemp()
|
||||||
@ -81,6 +81,24 @@ class TestMediaSync(unittest.TestCase):
|
|||||||
assert result.files_checked == 0
|
assert result.files_checked == 0
|
||||||
assert result.orphans_found == 0
|
assert result.orphans_found == 0
|
||||||
|
|
||||||
|
def test_sync_previews_scans_configured_recording_roots(self):
|
||||||
|
preview_dir = os.path.join(self.root_b, "preview", "front_door")
|
||||||
|
os.makedirs(preview_dir, exist_ok=True)
|
||||||
|
orphan_path = os.path.join(preview_dir, "100-200.mp4")
|
||||||
|
|
||||||
|
with open(orphan_path, "w"):
|
||||||
|
pass
|
||||||
|
|
||||||
|
result = sync_previews(
|
||||||
|
dry_run=True,
|
||||||
|
force=True,
|
||||||
|
recordings_roots=[self.root_a, self.root_b],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.files_checked == 1
|
||||||
|
assert result.orphans_found == 1
|
||||||
|
assert orphan_path in result.orphan_paths
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@ -506,7 +506,11 @@ def sync_review_thumbnails(dry_run: bool = False, force: bool = False) -> SyncRe
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def sync_previews(dry_run: bool = False, force: bool = False) -> SyncResult:
|
def sync_previews(
|
||||||
|
dry_run: bool = False,
|
||||||
|
force: bool = False,
|
||||||
|
recordings_roots: list[str] | None = None,
|
||||||
|
) -> SyncResult:
|
||||||
"""Sync preview files - delete files not referenced by any preview record.
|
"""Sync preview files - delete files not referenced by any preview record.
|
||||||
|
|
||||||
Preview files can exist in camera-specific recording roots at:
|
Preview files can exist in camera-specific recording roots at:
|
||||||
@ -528,6 +532,12 @@ def sync_previews(dry_run: bool = False, force: bool = False) -> SyncResult:
|
|||||||
for path in preview_paths
|
for path in preview_paths
|
||||||
if path and path.endswith(".mp4")
|
if path and path.endswith(".mp4")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Include configured recordings roots so orphaned previews are found even
|
||||||
|
# when they are not referenced by any DB row.
|
||||||
|
for root in recordings_roots or [RECORD_DIR]:
|
||||||
|
preview_dirs.add(os.path.join(root, "preview"))
|
||||||
|
|
||||||
preview_dirs.add(os.path.join(CLIPS_DIR, "previews"))
|
preview_dirs.add(os.path.join(CLIPS_DIR, "previews"))
|
||||||
|
|
||||||
preview_files: list[str] = []
|
preview_files: list[str] = []
|
||||||
@ -809,7 +819,11 @@ def sync_all_media(
|
|||||||
results.review_thumbnails = sync_review_thumbnails(dry_run=dry_run, force=force)
|
results.review_thumbnails = sync_review_thumbnails(dry_run=dry_run, force=force)
|
||||||
|
|
||||||
if sync_all or "previews" in media_types:
|
if sync_all or "previews" in media_types:
|
||||||
results.previews = sync_previews(dry_run=dry_run, force=force)
|
results.previews = sync_previews(
|
||||||
|
dry_run=dry_run,
|
||||||
|
force=force,
|
||||||
|
recordings_roots=recordings_roots,
|
||||||
|
)
|
||||||
|
|
||||||
if sync_all or "exports" in media_types:
|
if sync_all or "exports" in media_types:
|
||||||
results.exports = sync_exports(dry_run=dry_run, force=force)
|
results.exports = sync_exports(dry_run=dry_run, force=force)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user