feat: streamline camera config

This commit is contained in:
Jan-Henrik 2026-04-19 13:23:07 +02:00
parent 7c594a643d
commit 2cfe47cb3d
2 changed files with 107 additions and 143 deletions

View file

@ -43,6 +43,7 @@
default = pkgs.mkShell { default = pkgs.mkShell {
packages = [ packages = [
pkgs.colmena pkgs.colmena
pkgs.nixfmt
agenix.packages.${system}.default agenix.packages.${system}.default
]; ];
}; };

View file

@ -1,88 +1,8 @@
{ config, ... }: { { config, lib, ... }:
age.secrets."camera-ulfried-url".file = ../../secrets/camera-ulfried-url.age; let
age.secrets."camera-ulfried-sub-url".file = ../../secrets/camera-ulfried-sub-url.age; cameras = {
age.secrets."camera-gnisbert-url".file = ../../secrets/camera-gnisbert-url.age;
age.secrets."camera-gnisbert-sub-url".file = ../../secrets/camera-gnisbert-sub-url.age;
age.secrets."camera-taubis-url".file = ../../secrets/camera-taubis-url.age;
age.secrets."camera-taubis-sub-url".file = ../../secrets/camera-taubis-sub-url.age;
age.secrets."camera-foeff-url".file = ../../secrets/camera-foeff-url.age;
age.secrets."camera-foeff-sub-url".file = ../../secrets/camera-foeff-sub-url.age;
systemd.services.go2rtc.serviceConfig.LoadCredential = [
"ULFRIED_URL:${config.age.secrets."camera-ulfried-url".path}"
"ULFRIED_SUB_URL:${config.age.secrets."camera-ulfried-sub-url".path}"
"GNISBERT_URL:${config.age.secrets."camera-gnisbert-url".path}"
"GNISBERT_SUB_URL:${config.age.secrets."camera-gnisbert-sub-url".path}"
"TAUBIS_URL:${config.age.secrets."camera-taubis-url".path}"
"TAUBIS_SUB_URL:${config.age.secrets."camera-taubis-sub-url".path}"
"FOEFF_URL:${config.age.secrets."camera-foeff-url".path}"
"FOEFF_SUB_URL:${config.age.secrets."camera-foeff-sub-url".path}"
];
services.go2rtc.enable = true;
services.go2rtc.settings = {
rtsp.listen = ":8554";
webrtc.listen = ":8555";
};
services.go2rtc.settings.streams = {
"ulfried" = [
"\${ULFRIED_URL}"
"ffmpeg:ulfried#audio=opus#audio=aac"
];
"ulfried_sub" = [
"\${ULFRIED_SUB_URL}"
"ffmpeg:ulfried_sub#audio=opus#audio=aac"
];
"gnisbert" = [
"\${GNISBERT_URL}"
"ffmpeg:gnisbert#audio=opus#audio=aac"
];
"gnisbert_sub" = [
"\${GNISBERT_SUB_URL}"
"ffmpeg:gnisbert_sub#audio=opus#audio=aac"
];
"taubis" = [
"\${TAUBIS_URL}"
"ffmpeg:taubis#audio=opus#audio=aac"
];
"taubis_sub" = [
"\${TAUBIS_SUB_URL}"
"ffmpeg:taubis_sub#audio=opus#audio=aac"
];
"foeff" = [
"\${FOEFF_URL}"
"ffmpeg:foeff#audio=opus#audio=aac#video=copy"
];
"foeff_sub" = [
"\${FOEFF_SUB_URL}"
"ffmpeg:foeff_sub#audio=opus#audio=aac#video=copy"
];
};
services.frigate.enable = true;
services.frigate.hostname = "kameramann.lan.baubs.net";
services.frigate.settings.go2rtc = { streams = {
"ulfried" = [];
"ulfried_sub" = [];
"taubis" = [];
"taubis_sub" = [];
"foeff" = [];
"foeff_sub" = [];
"gnisbert" = [];
"gnisbert_sub" = [];
};};
services.frigate.settings.detect = {
enabled = true;
};
services.frigate.settings.objects = {
track = ["person" "bird" "car"];
};
services.frigate.settings.classification.bird.enabled = true;
services.frigate.settings.cameras = {
"ulfried" = { "ulfried" = {
record = { frigate.record = {
enabled = true; enabled = true;
continuous.days = 0; continuous.days = 0;
alerts.retain = { alerts.retain = {
@ -90,24 +10,21 @@
mode = "motion"; mode = "motion";
}; };
}; };
ffmpeg.inputs = [{ };
path = "rtsp://127.0.0.1:8554/ulfried?timeout=30"; "gnisbert" = { };
input_args = "preset-rtsp-generic"; "taubis" = {
roles = [ frigate = {
"record" detect.enabled = true;
]; record = {
} enabled = true;
{ continuous.days = 1;
path = "rtsp://127.0.0.1:8554/ulfried_sub?timeout=30"; detections.retain.days = 7;
input_args = "preset-rtsp-generic"; };
roles = [ };
"detect"
"audio"
];
}];
}; };
"foeff" = { "foeff" = {
record = { videoPassthrough = true;
frigate.record = {
enabled = true; enabled = true;
continuous.days = 0; continuous.days = 0;
alerts.retain = { alerts.retain = {
@ -115,51 +32,97 @@
mode = "motion"; mode = "motion";
}; };
}; };
ffmpeg.inputs = [
{
path = "rtsp://127.0.0.1:8554/foeff?timeout=30";
input_args = "preset-rtsp-generic";
roles = [
"record"
];
}
{
path = "rtsp://127.0.0.1:8554/foeff_sub?timeout=30";
input_args = "preset-rtsp-generic";
roles = [
"detect"
"audio"
];
}
];
};
"taubis" = {
detect.enabled = true;
record = {
enabled = true;
continuous.days = 1;
detections.retain.days = 7;
};
ffmpeg.inputs = [
{
path = "rtsp://127.0.0.1:8554/taubis?timeout=30";
input_args = "preset-rtsp-generic";
roles = [
"record"
];
}
{
path = "rtsp://127.0.0.1:8554/taubis_sub?timeout=30";
input_args = "preset-rtsp-generic";
roles = [
"detect"
"audio"
];
}
];
}; };
}; };
networking.firewall.allowedTCPPorts = [ 5000 1984 80 8555 ]; # Uppercase camera name for use as systemd credential / env var name
varName = name: lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);
go2rtcCameraStreams =
name: cam:
let
video = lib.optionalString (cam.videoPassthrough or false) "#video=copy";
in
{
"${name}" = [
"\${${varName name}_URL}"
"ffmpeg:${name}#audio=opus#audio=aac${video}"
];
"${name}_sub" = [
"\${${varName name}_SUB_URL}"
"ffmpeg:${name}_sub#audio=opus#audio=aac${video}"
];
};
frigateInputs = name: [
{
path = "rtsp://127.0.0.1:8554/${name}?timeout=30";
input_args = "preset-rtsp-generic";
roles = [ "record" ];
}
{
path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30";
input_args = "preset-rtsp-generic";
roles = [
"detect"
"audio"
];
}
];
# Only cameras with a frigate key get a frigate camera entry
frigCameras = lib.filterAttrs (_: cam: cam ? frigate) cameras;
in
{
age.secrets = lib.mkMerge (
lib.mapAttrsToList (name: _: {
"camera-${name}-url".file = ../../secrets/camera-${name}-url.age;
"camera-${name}-sub-url".file = ../../secrets/camera-${name}-sub-url.age;
}) cameras
);
systemd.services.go2rtc.serviceConfig.LoadCredential = lib.concatMap (name: [
"${varName name}_URL:${config.age.secrets."camera-${name}-url".path}"
"${varName name}_SUB_URL:${config.age.secrets."camera-${name}-sub-url".path}"
]) (lib.attrNames cameras);
services.go2rtc = {
enable = true;
settings = {
rtsp.listen = ":8554";
webrtc.listen = ":8555";
streams = lib.foldl' lib.mergeAttrs { } (lib.mapAttrsToList go2rtcCameraStreams cameras);
};
};
services.frigate = {
enable = true;
hostname = "kameramann.lan.baubs.net";
settings = {
go2rtc.streams = lib.foldl' lib.mergeAttrs { } (
lib.mapAttrsToList (name: _: {
"${name}" = [ ];
"${name}_sub" = [ ];
}) cameras
);
detect.enabled = true;
objects.track = [
"person"
"bird"
"car"
];
classification.bird.enabled = true;
cameras = lib.mapAttrs (
name: cam: cam.frigate // { ffmpeg.inputs = frigateInputs name; }
) frigCameras;
};
};
networking.firewall.allowedTCPPorts = [
5000
1984
80
8555
];
networking.firewall.allowedUDPPorts = [ 8555 ]; networking.firewall.allowedUDPPorts = [ 8555 ];
} }