frigate: centralize the ffmpeg flavor selection in the module

In 0.16.0 frigate added a config option to pass an ffmpeg build for the
ffmpeg and ffprobe executables.

Previously we unconditionally patched in ffmpeg-headless, which has now
been changed to use the `ffmpeg.path` provided build, so that we don't
bloat the closure with multiple ffmpegs or don't require overriding the
package to select another version.

In contrast to the upstream configuration we only accept packages and not
the "default" string, because that would have complicated the logic
needlessly.

Changed files
+34 -19
nixos
modules
services
video
pkgs
by-name
+11
nixos/modules/services/video/frigate.nix
···
};
};
+
ffmpeg = {
+
path = mkOption {
+
type = coercedTo package toString str;
+
default = pkgs.ffmpeg-headless;
+
example = literalExpression "pkgs.ffmpeg-full";
+
description = ''
+
Package providing the ffmpeg and ffprobe executables below the bin/ directory.
+
'';
+
};
+
};
+
mqtt = {
enabled = mkEnableOption "MQTT support";
+21 -13
pkgs/by-name/fr/frigate/ffmpeg.patch
···
diff --git a/frigate/config/camera/ffmpeg.py b/frigate/config/camera/ffmpeg.py
-
index 04bbfac7..4390a571 100644
+
index 04bbfac7..396bcc4b 100644
--- a/frigate/config/camera/ffmpeg.py
+++ b/frigate/config/camera/ffmpeg.py
-
@@ -70,18 +70,14 @@ class FfmpegConfig(FrigateBaseModel):
+
@@ -1,4 +1,5 @@
+
from enum import Enum
+
+from os.path import join
+
from typing import Union
+
+
from pydantic import Field, field_validator
+
@@ -69,21 +70,11 @@ class FfmpegConfig(FrigateBaseModel):
+
@property
def ffmpeg_path(self) -> str:
-
if self.path == "default":
+
- if self.path == "default":
- return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg"
- elif self.path in INCLUDED_FFMPEG_VERSIONS:
- return f"/usr/lib/ffmpeg/{self.path}/bin/ffmpeg"
-
+ return "@ffmpeg@"
-
else:
-
return f"{self.path}/bin/ffmpeg"
+
- else:
+
- return f"{self.path}/bin/ffmpeg"
+
+ return join(self.path, "bin/ffmpeg")
@property
def ffprobe_path(self) -> str:
-
if self.path == "default":
+
- if self.path == "default":
- return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffprobe"
- elif self.path in INCLUDED_FFMPEG_VERSIONS:
- return f"/usr/lib/ffmpeg/{self.path}/bin/ffprobe"
-
+ return "@ffprobe@"
-
else:
-
return f"{self.path}/bin/ffprobe"
+
- else:
+
- return f"{self.path}/bin/ffprobe"
+
+ return join(self.path, "bin/ffprobe")
+
+
class CameraRoleEnum(str, Enum):
diff --git a/frigate/record/export.py b/frigate/record/export.py
-
index 0d3f96da..09cadbcd 100644
+
index 0d3f96da..463bcff4 100644
--- a/frigate/record/export.py
+++ b/frigate/record/export.py
@@ -126,7 +126,7 @@ class RecordingExporter(threading.Thread):
···
seconds = int(diff % 60)
ffmpeg_cmd = [
- "/usr/lib/ffmpeg/7.0/bin/ffmpeg", # hardcode path for exports thumbnail due to missing libwebp support
-
+ "@ffmpeg@", # hardcode path for exports thumbnail due to missing libwebp support
+
+ FfmpegConfig.ffmpeg_path, # hardcode path for exports thumbnail due to missing libwebp support
"-hide_banner",
"-loglevel",
"warning",
-
~
+2 -6
pkgs/by-name/fr/frigate/package.nix
···
lib,
stdenv,
callPackage,
-
replaceVars,
python312Packages,
fetchFromGitHub,
fetchurl,
···
patches = [
./constants.patch
-
-
(replaceVars ./ffmpeg.patch {
-
ffmpeg = lib.getExe ffmpeg-headless;
-
ffprobe = lib.getExe' ffmpeg-headless "ffprobe";
-
})
+
./ffmpeg.patch
];
postPatch = ''
···
'';
nativeCheckInputs = with python3Packages; [
+
ffmpeg-headless
pytestCheckHook
];