nixos-config/nixos/modules/programs/ffmpeg.nix

162 lines
3.8 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.custom.ffmpeg;
ffmpegTemplate = name:
{ profile
, preset
, tune ? null
, width ? 1280
, height ? 720
, resolution ? "720p"
}:
pkgs.writeShellScriptBin "ffmpeg-${name}" ''
if [ $# -eq 0 ]
then
cat <<EOF
ffmpeg-<profile>-<preset>-<tunes>-${resolution} <input> <output>
profiles =
"baseline" - Primarily for low-cost applications that require additional data loss robustness
"main" - This profile is used for standard-definition digital TV broadcasts that use the MPEG-4 format as defined in the DVB standard.
"high" - The primary profile for broadcast and disc storage applications, particularly for high-definition television applications
presets =
"ultrafast"
"superfast"
"veryfast"
"faster"
"fast"
"medium"
"slow"
"slower"
"veryslow"
tunes = (optional)
"film" - use for high quality movie content; lowers deblockin
"animation" - good for cartoons; uses higher deblocking and more reference frames
"grain" - preserves the grain structure in old, grainy film material
"stillimage" - good for slideshow-like content
"fastdecode" - allows faster decoding by disabling certain filters
EOF
exit 0
fi
if [ $# -ne 2 ]
then
echo "ffmpeg-${name} <input> <output>"
exit 1
fi
input=$1
output=$2
if [ ! -f "$input" ]
then
echo "input does not exist $input"
exit 1
fi
# do it stereo
# -ac 2
# do it sample rate 44100
# -ar 44100
exec ${pkgs.ffmpeg}/bin/ffmpeg \
-i "$input" \
-filter:v scale=h='min(${toString height}\,ih)':w='min(${
toString width
}\,iw)' \
-vcodec libx264 \
-preset ${preset} \
-profile:v ${profile} \
${optionalString (tune != null) "-tune ${tune}"} \
-acodec aac \
-ac 2 \
-ar 44100 \
"$output" \
-hide_banner
'';
# https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
profiles = [
"baseline"
"main"
"high"
#"high10"
#"high422"
#"high44"
];
presets = [
#"ultrafast"
#"superfast"
#"veryfast"
#"faster"
"fast"
"medium"
"slow"
#"slower"
"veryslow"
];
tunes = [ "film" "animation" "grain" "stillimage" "fastdecode" ];
ffmpegs =
let
configurations = lib.cartesianProductOfSets {
profile = profiles;
preset = presets;
};
p720 = { profile, preset }:
ffmpegTemplate "${profile}-${preset}-720p" { inherit profile preset; };
p1080 = { profile, preset }:
ffmpegTemplate "${profile}-${preset}-1080p" {
inherit profile preset;
height = 1080;
width = 1920;
resolution = "1080p";
};
in
(map p720 configurations) ++ (map p1080 configurations);
ffmpegsTune =
let
configurations = lib.cartesianProductOfSets {
profile = profiles;
preset = presets;
tune = tunes;
};
p720 = { profile, preset, tune }:
ffmpegTemplate "${profile}-${preset}-${tune}-720p" {
inherit profile preset tune;
};
p1080 = { profile, preset, tune }:
ffmpegTemplate "${profile}-${preset}-${tune}-1080p" {
inherit profile preset tune;
height = 1080;
width = 1920;
resolution = "1080p";
};
in
(map p720 configurations) ++ (map p1080 configurations);
in
{
options.programs.custom.ffmpeg = {
enable = mkEnableOption "enable programs.custom.ffmpeg";
};
config =
mkIf cfg.enable { environment.systemPackages = ffmpegs ++ ffmpegsTune; };
}