frigate: 0.12.1 -> 0.13.1

Changelog:
https://github.com/blakeblackshear/frigate/releases/tag/v0.13.0
https://github.com/blakeblackshear/frigate/releases/tag/v0.13.1

Co-Authored-By: Martin Weinelt <hexa@darmstadt.ccc.de>
This commit is contained in:
fleaz 2024-02-01 23:09:56 +01:00
parent b6eaf6269a
commit 250078ceba
No known key found for this signature in database
GPG Key ID: AED15F8FDD04D083
4 changed files with 136 additions and 73 deletions

View File

@ -17,7 +17,7 @@ let
cfg = config.services.frigate; cfg = config.services.frigate;
format = pkgs.formats.yaml {}; format = pkgs.formats.yaml { };
filteredConfig = lib.converge (lib.filterAttrsRecursive (_: v: ! lib.elem v [ null ])) cfg.settings; filteredConfig = lib.converge (lib.filterAttrsRecursive (_: v: ! lib.elem v [ null ])) cfg.settings;
@ -112,7 +112,7 @@ in
}; };
}; };
}; };
default = {}; default = { };
description = mdDoc '' description = mdDoc ''
Frigate configuration as a nix attribute set. Frigate configuration as a nix attribute set.
@ -125,7 +125,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.nginx = { services.nginx = {
enable =true; enable = true;
additionalModules = with pkgs.nginxModules; [ additionalModules = with pkgs.nginxModules; [
secure-token secure-token
rtmp rtmp
@ -133,31 +133,64 @@ in
]; ];
recommendedProxySettings = mkDefault true; recommendedProxySettings = mkDefault true;
recommendedGzipSettings = mkDefault true; recommendedGzipSettings = mkDefault true;
mapHashBucketSize = mkDefault 128;
upstreams = { upstreams = {
frigate-api.servers = { frigate-api.servers = {
"127.0.0.1:5001" = {}; "127.0.0.1:5001" = { };
}; };
frigate-mqtt-ws.servers = { frigate-mqtt-ws.servers = {
"127.0.0.1:5002" = {}; "127.0.0.1:5002" = { };
}; };
frigate-jsmpeg.servers = { frigate-jsmpeg.servers = {
"127.0.0.1:8082" = {}; "127.0.0.1:8082" = { };
}; };
frigate-go2rtc.servers = { frigate-go2rtc.servers = {
"127.0.0.1:1984" = {}; "127.0.0.1:1984" = { };
}; };
}; };
# Based on https://github.com/blakeblackshear/frigate/blob/v0.12.0/docker/rootfs/usr/local/nginx/conf/nginx.conf proxyCachePath."frigate" = {
enable = true;
keysZoneSize = "10m";
keysZoneName = "frigate_api_cache";
maxSize = "10m";
inactive = "1m";
levels = "1:2";
};
# Based on https://github.com/blakeblackshear/frigate/blob/v0.13.1/docker/main/rootfs/usr/local/nginx/conf/nginx.conf
virtualHosts."${cfg.hostname}" = { virtualHosts."${cfg.hostname}" = {
locations = { locations = {
"/api/" = { "/api/" = {
proxyPass = "http://frigate-api/"; proxyPass = "http://frigate-api/";
extraConfig = ''
proxy_cache frigate_api_cache;
proxy_cache_lock on;
proxy_cache_use_stale updating;
proxy_cache_valid 200 5s;
proxy_cache_bypass $http_x_cache_bypass;
proxy_no_cache $should_not_cache;
add_header X-Cache-Status $upstream_cache_status;
location /api/vod/ {
proxy_pass http://frigate-api/vod/;
proxy_cache off;
}
location /api/stats {
access_log off;
rewrite ^/api/(.*)$ $1 break;
proxy_pass http://frigate-api;
}
location /api/version {
access_log off;
rewrite ^/api/(.*)$ $1 break;
proxy_pass http://frigate-api;
}
'';
}; };
"~* /api/.*\.(jpg|jpeg|png)$" = { "~* /api/.*\.(jpg|jpeg|png)$" = {
proxyPass = "http://frigate-api"; proxyPass = "http://frigate-api";
extraConfig = '' extraConfig = ''
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
rewrite ^/api/(.*)$ $1 break; rewrite ^/api/(.*)$ $1 break;
''; '';
}; };
@ -169,10 +202,6 @@ in
secure_token $args; secure_token $args;
secure_token_types application/vnd.apple.mpegurl; secure_token_types application/vnd.apple.mpegurl;
add_header Access-Control-Allow-Headers '*';
add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
add_header Access-Control-Allow-Origin '*';
add_header Cache-Control "no-store"; add_header Cache-Control "no-store";
expires off; expires off;
''; '';
@ -192,27 +221,64 @@ in
proxyPass = "http://frigate-go2rtc/"; proxyPass = "http://frigate-go2rtc/";
proxyWebsockets = true; proxyWebsockets = true;
}; };
# frigate lovelace card uses this path
"/live/mse/api/ws" = {
proxyPass = "http://frigate-go2rtc/api/ws";
proxyWebsockets = true;
extraConfig = ''
limit_except GET {
deny all;
}
'';
};
"/live/webrtc/" = { "/live/webrtc/" = {
proxyPass = "http://frigate-go2rtc/"; proxyPass = "http://frigate-go2rtc/";
proxyWebsockets = true; proxyWebsockets = true;
}; };
"/live/webrtc/api/ws" = {
proxyPass = "http://frigate-go2rtc/api/ws";
proxyWebsockets = true;
extraConfig = ''
limit_except GET {
deny all;
}
'';
};
# pass through go2rtc player
"/live/webrtc/webrtc.html" = {
proxyPass = "http://frigate-go2rtc/webrtc.html";
proxyWebsockets = true;
extraConfig = ''
limit_except GET {
deny all;
}
'';
};
"/api/go2rtc/api" = {
proxyPass = "http://frigate-go2rtc/api";
proxyWebsockets = true;
extraConfig = ''
limit_except GET {
deny all;
}
'';
};
# integrationn uses this to add webrtc candidate
"/api/go2rtc/webrtc" = {
proxyPass = "http://frigate-go2rtc/api/webrtc";
proxyWebsockets = true;
extraConfig = ''
limit_except GET {
deny all;
}
'';
};
"/cache/" = { "/cache/" = {
alias = "/var/cache/frigate/"; alias = "/var/cache/frigate/";
}; };
"/clips/" = { "/clips/" = {
root = "/var/lib/frigate"; root = "/var/lib/frigate";
extraConfig = '' extraConfig = ''
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Expose-Headers' 'Content-Length';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types { types {
video/mp4 mp4; video/mp4 mp4;
image/jpeg jpg; image/jpeg jpg;
@ -224,17 +290,6 @@ in
"/recordings/" = { "/recordings/" = {
root = "/var/lib/frigate"; root = "/var/lib/frigate";
extraConfig = '' extraConfig = ''
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Expose-Headers' 'Content-Length';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types { types {
video/mp4 mp4; video/mp4 mp4;
} }
@ -315,6 +370,12 @@ in
} }
} }
''; '';
appendHttpConfig = ''
map $sent_http_content_type $should_not_cache {
'application/json' 0;
default 1;
}
'';
}; };
systemd.services.nginx.serviceConfig.SupplementaryGroups = [ systemd.services.nginx.serviceConfig.SupplementaryGroups = [
@ -325,7 +386,7 @@ in
isSystemUser = true; isSystemUser = true;
group = "frigate"; group = "frigate";
}; };
users.groups.frigate = {}; users.groups.frigate = { };
systemd.services.frigate = { systemd.services.frigate = {
after = [ after = [

View File

@ -41,6 +41,7 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
serviceConfig = { serviceConfig = {
DynamicUser = true; DynamicUser = true;
ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -f mpegts -listen 1 http://0.0.0.0:8080"; ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -f mpegts -listen 1 http://0.0.0.0:8080";
Restart = "always";
}; };
}; };
}; };
@ -51,10 +52,14 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
machine.wait_for_unit("frigate.service") machine.wait_for_unit("frigate.service")
# Frigate startup
machine.wait_for_open_port(5001) machine.wait_for_open_port(5001)
machine.succeed("curl http://localhost:5001") # nginx startup
machine.wait_for_open_port(80)
machine.wait_for_file("/var/cache/frigate/test-*.mp4") machine.succeed("curl http://localhost")
machine.wait_for_file("/var/cache/frigate/test@*.mp4")
''; '';
}) })

View File

@ -3,20 +3,19 @@
, python3 , python3
, fetchFromGitHub , fetchFromGitHub
, fetchurl , fetchurl
, fetchpatch
, frigate , frigate
, nixosTests , nixosTests
}: }:
let let
version = "0.12.1"; version = "0.13.1";
src = fetchFromGitHub { src = fetchFromGitHub {
#name = "frigate-${version}-source"; #name = "frigate-${version}-source";
owner = "blakeblackshear"; owner = "blakeblackshear";
repo = "frigate"; repo = "frigate";
rev = "refs/tags/v${version}"; rev = "refs/tags/v${version}";
hash = "sha256-kNvYsHoObi6b9KT/LYhTGK4uJ/uAHnYhyoQkiXIA/s8="; hash = "sha256-2J7DhnYDX9ubbsk0qhji/vIKDouy9IqQztzbdPj2kxo=";
}; };
frigate-web = callPackage ./web.nix { frigate-web = callPackage ./web.nix {
@ -35,7 +34,7 @@ let
}; };
# Tensorflow Lite models # Tensorflow Lite models
# https://github.com/blakeblackshear/frigate/blob/v0.12.0/Dockerfile#L88-L91 # https://github.com/blakeblackshear/frigate/blob/v0.13.0/docker/main/Dockerfile#L96-L97
tflite_cpu_model = fetchurl { tflite_cpu_model = fetchurl {
url = "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite"; url = "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite";
hash = "sha256-kLszpjTgQZFMwYGapd+ZgY5sOWxNLblSwP16nP/Eck8="; hash = "sha256-kLszpjTgQZFMwYGapd+ZgY5sOWxNLblSwP16nP/Eck8=";
@ -46,7 +45,7 @@ let
}; };
# OpenVino models # OpenVino models
# https://github.com/blakeblackshear/frigate/blob/v0.12.0/Dockerfile#L92-L95 # https://github.com/blakeblackshear/frigate/blob/v0.13.0/docker/main/Dockerfile#L101
openvino_model = fetchurl { openvino_model = fetchurl {
url = "https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt"; url = "https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt";
hash = "sha256-5Cj2vEiWR8Z9d2xBmVoLZuNRv4UOuxHSGZQWTJorXUQ="; hash = "sha256-5Cj2vEiWR8Z9d2xBmVoLZuNRv4UOuxHSGZQWTJorXUQ=";
@ -59,14 +58,6 @@ python.pkgs.buildPythonApplication rec {
inherit src; inherit src;
patches = [
(fetchpatch {
# numpy 1.24 compat
url = "https://github.com/blakeblackshear/frigate/commit/cb73d0cd392990448811c7212bc5f09be411fc69.patch";
hash = "sha256-Spt7eRosmTN8zyJ2uVme5HPVy2TKgBtvbQ6tp6PaNac=";
})
];
postPatch = '' postPatch = ''
echo 'VERSION = "${version}"' > frigate/version.py echo 'VERSION = "${version}"' > frigate/version.py
@ -75,58 +66,59 @@ python.pkgs.buildPythonApplication rec {
substituteInPlace frigate/const.py \ substituteInPlace frigate/const.py \
--replace "/media/frigate" "/var/lib/frigate" \ --replace "/media/frigate" "/var/lib/frigate" \
--replace "/tmp/cache" "/var/cache/frigate/" --replace "/tmp/cache" "/var/cache/frigate" \
--replace "/config" "/var/lib/frigate" \
--replace "{CONFIG_DIR}/model_cache" "/var/cache/frigate/model_cache"
substituteInPlace frigate/http.py \ substituteInPlace frigate/http.py \
--replace "/opt/frigate" "${placeholder "out"}/${python.sitePackages}" \ --replace "/opt/frigate" "${placeholder "out"}/${python.sitePackages}"
--replace "/tmp/cache/" "/var/cache/frigate/"
substituteInPlace frigate/output.py \ substituteInPlace frigate/output.py \
--replace "/opt/frigate" "${placeholder "out"}/${python.sitePackages}" --replace "/opt/frigate" "${placeholder "out"}/${python.sitePackages}"
substituteInPlace frigate/record.py \
--replace "/tmp/cache" "/var/cache/frigate"
substituteInPlace frigate/detectors/detector_config.py \ substituteInPlace frigate/detectors/detector_config.py \
--replace "/labelmap.txt" "${placeholder "out"}/share/frigate/labelmap.txt" --replace "/labelmap.txt" "${placeholder "out"}/share/frigate/labelmap.txt"
substituteInPlace frigate/detectors/plugins/edgetpu_tfl.py \ substituteInPlace frigate/config.py \
--replace "/cpu_model.tflite" "${tflite_cpu_model}" \
--replace "/edgetpu_model.tflite" "${tflite_edgetpu_model}" --replace "/edgetpu_model.tflite" "${tflite_edgetpu_model}"
substituteInPlace frigate/detectors/plugins/cpu_tfl.py \ substituteInPlace frigate/test/test_config.py \
--replace "/cpu_model.tflite" "${tflite_cpu_model}" --replace "(MODEL_CACHE_DIR" "('/build/model_cache'" \
--replace "/config/model_cache" "/build/model_cache"
substituteInPlace frigate/ffmpeg_presets.py --replace \
'"-timeout" if os.path.exists(BTBN_PATH) else "-stimeout"' \
'"-timeout"'
''; '';
dontBuild = true; dontBuild = true;
propagatedBuildInputs = with python.pkgs; [ propagatedBuildInputs = with python.pkgs; [
# requirements.txt # docker/main/requirements.txt
scikit-build scikit-build
# requirements-wheel.txt # docker/main/requirements-wheel.txt
click click
flask flask
imutils imutils
matplotlib matplotlib
norfair
numpy numpy
onvif-zeep
opencv4 opencv4
openvino openvino
paho-mqtt paho-mqtt
peewee peewee
peewee-migrate peewee-migrate
psutil psutil
py3nvml
pydantic pydantic
pytz
pyyaml pyyaml
requests requests
ruamel-yaml
scipy scipy
setproctitle setproctitle
tensorflow tensorflow
tzlocal tzlocal
unidecode
ws4py ws4py
zeroconf
]; ];
installPhase = '' installPhase = ''
@ -144,10 +136,15 @@ python.pkgs.buildPythonApplication rec {
runHook postInstall runHook postInstall
''; '';
checkInputs = with python.pkgs; [ nativeCheckInputs = with python.pkgs; [
pytestCheckHook pytestCheckHook
]; ];
disabledTests = [
# Test needs network access
"test_plus_labelmap"
];
passthru = { passthru = {
web = frigate-web; web = frigate-web;
inherit python; inherit python;

View File

@ -11,14 +11,14 @@ buildNpmPackage {
postPatch = '' postPatch = ''
substituteInPlace package.json \ substituteInPlace package.json \
--replace "--base=/BASE_PATH/" "" --replace-fail "--base=/BASE_PATH/" ""
substituteInPlace src/routes/Storage.jsx \ substituteInPlace src/routes/Storage.jsx \
--replace "/media/frigate" "/var/lib/frigate" \ --replace-fail "/media/frigate" "/var/lib/frigate" \
--replace "/tmp/cache" "/var/cache/frigate" --replace-fail "/tmp/cache" "/var/cache/frigate"
''; '';
npmDepsHash = "sha256-fvRxpQjSEzd2CnoEOVgQcB6MJJ4dcjN8bOaacHjCdwU="; npmDepsHash = "sha256-+36quezGArqIM9dM+UihwcIgmE3EVmJQThuicLgDW4A=";
installPhase = '' installPhase = ''
cp -rv dist/ $out cp -rv dist/ $out