Serve preview files from non-default recording roots via nginx

When cameras are configured with recording paths outside /media/frigate
(e.g. /video1, /video2), preview mp4 files generated there had no
corresponding nginx location block — requests returned 404.

At nginx startup, get_nginx_settings.py now extracts unique recording
roots outside /media/frigate from the Frigate config. The nginx run
script uses a new extra_recordings.gotmpl template to generate
location blocks (e.g. /video1/preview/) with alias directives for
each such root, included via extra_recordings.conf.

The API already returns correct src URLs for these paths (the existing
replace(BASE_DIR, "") leaves non-media paths unchanged), so no API
changes are needed.

https://claude.ai/code/session_016bxjbVpx8DqpjysnGYmXdx
This commit is contained in:
Claude 2026-03-13 09:01:56 +00:00
parent 6248dbf12f
commit 5ba7802316
No known key found for this signature in database
4 changed files with 29 additions and 0 deletions

View File

@ -89,6 +89,11 @@ python3 /usr/local/nginx/get_nginx_settings.py | \
tempio -template /usr/local/nginx/templates/listen.gotmpl \
-out /usr/local/nginx/conf/listen.conf
# build location blocks for recording roots outside /media/frigate
python3 /usr/local/nginx/get_nginx_settings.py | \
tempio -template /usr/local/nginx/templates/extra_recordings.gotmpl \
-out /usr/local/nginx/conf/extra_recordings.conf
# Replace the bash process with the NGINX process, redirecting stderr to stdout
exec 2>&1
exec \

View File

@ -101,6 +101,7 @@ http {
include auth_location.conf;
include base_path.conf;
include extra_recordings.conf;
location /vod/ {
include auth_request.conf;

View File

@ -52,11 +52,22 @@ listen_config["external_port"] = external_port
base_path = os.environ.get("FRIGATE_BASE_PATH", "")
# Collect recording roots that are outside the default /media/frigate tree.
# Nginx needs an explicit location block for each such root to serve preview files.
_default_recordings = "/media/frigate"
_extra_roots: set[str] = set()
for _cam_cfg in config.get("cameras", {}).values():
if isinstance(_cam_cfg, dict):
_path = _cam_cfg.get("path", "")
if _path and not _path.startswith(_default_recordings):
_extra_roots.add(_path.rstrip("/"))
result: dict[str, Any] = {
"tls": tls_config,
"ipv6": ipv6_config,
"listen": listen_config,
"base_path": base_path,
"extra_recording_roots": sorted(_extra_roots),
}
print(json.dumps(result))

View File

@ -0,0 +1,12 @@
{{ range .extra_recording_roots }}
location {{ . }}/preview/ {
include auth_request.conf;
types {
video/mp4 mp4;
}
expires 7d;
add_header Cache-Control "public";
alias {{ . }}/preview/;
}
{{ end }}