From 189b9c6648b2ae14fac3d5fbed740885d370fb31 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 10 Aug 2021 08:27:31 -0500 Subject: [PATCH] use a nginx internal redirect --- docker/rootfs/usr/local/nginx/conf/nginx.conf | 5 ++ frigate/http.py | 50 ++++++++++--------- frigate/record.py | 2 +- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/docker/rootfs/usr/local/nginx/conf/nginx.conf b/docker/rootfs/usr/local/nginx/conf/nginx.conf index adc5c549e..259d2668a 100644 --- a/docker/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/rootfs/usr/local/nginx/conf/nginx.conf @@ -125,6 +125,11 @@ http { root /media/frigate; } + location /cache/ { + internal; # This tells nginx it's not accessible from the outside + alias /tmp/cache/; + } + location /recordings/ { add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true'; diff --git a/frigate/http.py b/frigate/http.py index ed441a88c..cef448beb 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -245,17 +245,24 @@ def event_clip(id): event_config = current_app.frigate_config.cameras[event.camera].record.events start_ts = event.start_time - event_config.pre_capture end_ts = event.end_time + event_config.post_capture - clip_path = os.path.join(CLIPS_DIR, f"{event.camera}-{id}.mp4") + file_name = f"{event.camera}-{id}.mp4" + clip_path = os.path.join(CLIPS_DIR, file_name) if not os.path.isfile(clip_path): return recording_clip(event.camera, start_ts, end_ts) - return send_file( - clip_path, - mimetype="video/mp4", - as_attachment=download, - attachment_filename=f"{event.camera}_{start_ts}-{end_ts}.mp4", - ) + response = make_response() + response.headers["Content-Description"] = "File Transfer" + response.headers["Cache-Control"] = "no-cache" + response.headers["Content-Type"] = "video/mp4" + if download: + response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name + response.headers["Content-Length"] = os.path.getsize(clip_path) + response.headers[ + "X-Accel-Redirect" + ] = f"/clips/{file_name}" # nginx: http://wiki.nginx.org/NginxXSendfile + + return response @bp.route("/events") @@ -579,7 +586,8 @@ def recording_clip(camera, start_ts, end_ts): if clip.end_time > end_ts: playlist_lines.append(f"outpoint {int(end_ts - clip.start_time)}") - path = f"/tmp/cache/tmp_clip_{camera}_{start_ts}-{end_ts}.mp4" + file_name = f"clip_{camera}_{start_ts}-{end_ts}.mp4" + path = f"/tmp/cache/{file_name}" ffmpeg_cmd = [ "ffmpeg", @@ -609,23 +617,17 @@ def recording_clip(camera, start_ts, end_ts): logger.error(p.stderr) return f"Could not create clip from recordings for {camera}.", 500 - mp4_bytes = None - try: - # read clip from disk - with open(path, "rb") as mp4_file: - mp4_bytes = mp4_file.read() - - # delete after we have the bytes - os.remove(path) - except DoesNotExist: - return f"Could not create clip from recordings for {camera}.", 500 - - response = make_response(mp4_bytes) - response.mimetype = "video/mp4" + response = make_response() + response.headers["Content-Description"] = "File Transfer" + response.headers["Cache-Control"] = "no-cache" + response.headers["Content-Type"] = "video/mp4" if download: - response.headers[ - "Content-Disposition" - ] = f"attachment; filename={camera}_{start_ts}-{end_ts}.mp4" + 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: http://wiki.nginx.org/NginxXSendfile + return response diff --git a/frigate/record.py b/frigate/record.py index 26693e820..d7fdaf12e 100644 --- a/frigate/record.py +++ b/frigate/record.py @@ -51,7 +51,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("tmp_clip") + and not d.startswith("clip_") ] files_in_use = []