move clip.mp4 backend to clips folder (#11834)

* move clip.mp4 backend to clips folder

* improve caching

* fix check
This commit is contained in:
Blake Blackshear 2024-06-09 13:45:26 -05:00 committed by GitHub
parent 5f3c35209d
commit 30b86271ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 23 additions and 12 deletions

View File

@ -131,6 +131,8 @@ http {
image/jpeg jpg; image/jpeg jpg;
} }
expires 7d;
add_header Cache-Control "public";
autoindex on; autoindex on;
root /media/frigate; root /media/frigate;
} }

View File

@ -459,7 +459,7 @@ def recording_clip(camera_name, start_ts, end_ts):
) )
file_name = secure_filename(file_name) 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): if not os.path.exists(path):
ffmpeg_cmd = [ 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-Disposition"] = "attachment; filename=%s" % file_name
response.headers["Content-Length"] = os.path.getsize(path) response.headers["Content-Length"] = os.path.getsize(path)
response.headers["X-Accel-Redirect"] = ( 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 return response
@ -1232,8 +1232,8 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):
@MediaBp.route("/<camera_name>/start/<int:start_ts>/end/<int:end_ts>/preview.mp4") @MediaBp.route("/<camera_name>/start/<int:start_ts>/end/<int:end_ts>/preview.mp4")
@MediaBp.route("/<camera_name>/start/<float:start_ts>/end/<float:end_ts>/preview.mp4") @MediaBp.route("/<camera_name>/start/<float:start_ts>/end/<float:end_ts>/preview.mp4")
def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=2592000): def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=604800):
file_name = f"clip_{camera_name}_{start_ts}-{end_ts}.mp4" file_name = f"preview_{camera_name}_{start_ts}-{end_ts}.mp4"
if len(file_name) > 1000: if len(file_name) > 1000:
return make_response( return make_response(

View File

@ -100,7 +100,7 @@ class FrigateApp:
for d in [ for d in [
CONFIG_DIR, CONFIG_DIR,
RECORD_DIR, RECORD_DIR,
CLIPS_DIR, f"{CLIPS_DIR}/cache",
CACHE_DIR, CACHE_DIR,
MODEL_CACHE_DIR, MODEL_CACHE_DIR,
EXPORT_DIR, EXPORT_DIR,

View File

@ -11,7 +11,7 @@ from pathlib import Path
from playhouse.sqlite_ext import SqliteExtDatabase from playhouse.sqlite_ext import SqliteExtDatabase
from frigate.config import CameraConfig, FrigateConfig, RetainModeEnum 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.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
@ -28,11 +28,19 @@ class RecordingCleanup(threading.Thread):
self.config = config self.config = config
self.stop_event = stop_event 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: def clean_tmp_clips(self) -> None:
"""delete any clips in the cache that are more than 5 minutes old.""" """delete any clips in the cache that are more than 1 hour old."""
for p in Path(CACHE_DIR).rglob("clip_*.mp4"): for p in Path(os.path.join(CLIPS_DIR, "cache")).rglob("clip_*.mp4"):
logger.debug(f"Checking tmp clip {p}.") 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.") logger.debug("Deleting tmp clip.")
clear_and_unlink(p) clear_and_unlink(p)
@ -335,7 +343,7 @@ class RecordingCleanup(threading.Thread):
logger.info("Exiting recording cleanup...") logger.info("Exiting recording cleanup...")
break break
self.clean_tmp_clips() self.clean_tmp_previews()
if ( if (
self.config.record.sync_recordings self.config.record.sync_recordings
@ -346,6 +354,7 @@ class RecordingCleanup(threading.Thread):
next_sync = get_tomorrow_at_time(3) next_sync = get_tomorrow_at_time(3)
if counter == 0: if counter == 0:
self.clean_tmp_clips()
self.expire_recordings() self.expire_recordings()
remove_empty_directories(RECORD_DIR) remove_empty_directories(RECORD_DIR)
self.truncate_wal() self.truncate_wal()

View File

@ -82,7 +82,7 @@ class RecordingMaintainer(threading.Thread):
for d in os.listdir(CACHE_DIR) for d in os.listdir(CACHE_DIR)
if os.path.isfile(os.path.join(CACHE_DIR, d)) if os.path.isfile(os.path.join(CACHE_DIR, d))
and d.endswith(".mp4") and d.endswith(".mp4")
and not d.startswith("clip_") and not d.startswith("preview_")
] ]
files_in_use = [] files_in_use = []

View File

@ -300,7 +300,7 @@ class CameraWatchdog(threading.Thread):
for d in os.listdir(CACHE_DIR) for d in os.listdir(CACHE_DIR)
if os.path.isfile(os.path.join(CACHE_DIR, d)) if os.path.isfile(os.path.join(CACHE_DIR, d))
and d.endswith(".mp4") and d.endswith(".mp4")
and not d.startswith("clip_") and not d.startswith("preview_")
] ]
) )
newest_segment_time = latest_segment newest_segment_time = latest_segment