From 30b86271ea1ad1ee95954d2f17325af653e107ea Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sun, 9 Jun 2024 13:45:26 -0500 Subject: [PATCH] move clip.mp4 backend to clips folder (#11834) * move clip.mp4 backend to clips folder * improve caching * fix check --- .../rootfs/usr/local/nginx/conf/nginx.conf | 2 ++ frigate/api/media.py | 8 ++++---- frigate/app.py | 2 +- frigate/record/cleanup.py | 19 ++++++++++++++----- frigate/record/maintainer.py | 2 +- frigate/video.py | 2 +- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf index bcd135e51..7bf7ef59e 100644 --- a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf @@ -131,6 +131,8 @@ http { image/jpeg jpg; } + expires 7d; + add_header Cache-Control "public"; autoindex on; root /media/frigate; } diff --git a/frigate/api/media.py b/frigate/api/media.py index 21abe0591..8222fddaf 100644 --- a/frigate/api/media.py +++ b/frigate/api/media.py @@ -459,7 +459,7 @@ def recording_clip(camera_name, start_ts, end_ts): ) file_name = secure_filename(file_name) - path = os.path.join(CACHE_DIR, file_name) + path = os.path.join(CLIPS_DIR, f"cache/{file_name}") if not os.path.exists(path): ffmpeg_cmd = [ @@ -511,7 +511,7 @@ def recording_clip(camera_name, start_ts, end_ts): response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name response.headers["Content-Length"] = os.path.getsize(path) response.headers["X-Accel-Redirect"] = ( - f"/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers + f"/clips/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers ) return response @@ -1232,8 +1232,8 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000): @MediaBp.route("//start//end//preview.mp4") @MediaBp.route("//start//end//preview.mp4") -def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=2592000): - file_name = f"clip_{camera_name}_{start_ts}-{end_ts}.mp4" +def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=604800): + file_name = f"preview_{camera_name}_{start_ts}-{end_ts}.mp4" if len(file_name) > 1000: return make_response( diff --git a/frigate/app.py b/frigate/app.py index a157ad294..e2716a8a2 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -100,7 +100,7 @@ class FrigateApp: for d in [ CONFIG_DIR, RECORD_DIR, - CLIPS_DIR, + f"{CLIPS_DIR}/cache", CACHE_DIR, MODEL_CACHE_DIR, EXPORT_DIR, diff --git a/frigate/record/cleanup.py b/frigate/record/cleanup.py index c45ea032d..6f4e3c29f 100644 --- a/frigate/record/cleanup.py +++ b/frigate/record/cleanup.py @@ -11,7 +11,7 @@ from pathlib import Path from playhouse.sqlite_ext import SqliteExtDatabase from frigate.config import CameraConfig, FrigateConfig, RetainModeEnum -from frigate.const import CACHE_DIR, MAX_WAL_SIZE, RECORD_DIR +from frigate.const import CACHE_DIR, CLIPS_DIR, MAX_WAL_SIZE, RECORD_DIR from frigate.models import Event, Previews, Recordings, ReviewSegment from frigate.record.util import remove_empty_directories, sync_recordings from frigate.util.builtin import clear_and_unlink, get_tomorrow_at_time @@ -28,11 +28,19 @@ class RecordingCleanup(threading.Thread): self.config = config self.stop_event = stop_event + def clean_tmp_previews(self) -> None: + """delete any previews in the cache that are more than 1 hour old.""" + for p in Path(CACHE_DIR).rglob("preview_*.mp4"): + logger.debug(f"Checking preview {p}.") + if p.stat().st_mtime < (datetime.datetime.now().timestamp() - 60 * 60): + logger.debug("Deleting preview.") + clear_and_unlink(p) + def clean_tmp_clips(self) -> None: - """delete any clips in the cache that are more than 5 minutes old.""" - for p in Path(CACHE_DIR).rglob("clip_*.mp4"): + """delete any clips in the cache that are more than 1 hour old.""" + for p in Path(os.path.join(CLIPS_DIR, "cache")).rglob("clip_*.mp4"): logger.debug(f"Checking tmp clip {p}.") - if p.stat().st_mtime < (datetime.datetime.now().timestamp() - 60 * 1): + if p.stat().st_mtime < (datetime.datetime.now().timestamp() - 60 * 60): logger.debug("Deleting tmp clip.") clear_and_unlink(p) @@ -335,7 +343,7 @@ class RecordingCleanup(threading.Thread): logger.info("Exiting recording cleanup...") break - self.clean_tmp_clips() + self.clean_tmp_previews() if ( self.config.record.sync_recordings @@ -346,6 +354,7 @@ class RecordingCleanup(threading.Thread): next_sync = get_tomorrow_at_time(3) if counter == 0: + self.clean_tmp_clips() self.expire_recordings() remove_empty_directories(RECORD_DIR) self.truncate_wal() diff --git a/frigate/record/maintainer.py b/frigate/record/maintainer.py index 072c80327..188c1c3eb 100644 --- a/frigate/record/maintainer.py +++ b/frigate/record/maintainer.py @@ -82,7 +82,7 @@ class RecordingMaintainer(threading.Thread): for d in os.listdir(CACHE_DIR) if os.path.isfile(os.path.join(CACHE_DIR, d)) and d.endswith(".mp4") - and not d.startswith("clip_") + and not d.startswith("preview_") ] files_in_use = [] diff --git a/frigate/video.py b/frigate/video.py index 255d8466b..1c74575dc 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -300,7 +300,7 @@ class CameraWatchdog(threading.Thread): for d in os.listdir(CACHE_DIR) if os.path.isfile(os.path.join(CACHE_DIR, d)) and d.endswith(".mp4") - and not d.startswith("clip_") + and not d.startswith("preview_") ] ) newest_segment_time = latest_segment