nixos-config/users/simon/modules/mpv/default.nix
Simon Bruder 8f7403e66f
mpv: Overhaul selection of shader-based scalers
This removes ravu-zoom and ravu-lite in favour of standard ravu. It also
adds more nnedi3 shaders with neurons between 2^4 and 2^8, each with a
window size of 8x4. This should give a wide range of options that work
on all machines and still give acceptable results (at least balanced to
the performance).

The reason for this switch is ravu’s subpar performance, since it often
produces more artifacts than it avoids.

It also avoids some code duplication at the cost of making it more
complex.
2022-03-14 22:57:35 +01:00

275 lines
8.5 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ config, lib, nixosConfig, pkgs, ... }:
let
mpv-prescalers = pkgs.fetchFromGitHub {
owner = "bjin";
repo = "mpv-prescalers";
rev = "b37d0f12223720f5ce48e149678162ae0a984176";
sha256 = "1mmf5827qsyph0wqkyvi7zfng1cskkapngn5hf9073zc61n4398y";
meta.license = lib.licenses.lgpl3Plus;
};
shaders = {
fsrcnnx_x2 = pkgs.fetchurl {
url = "https://github.com/igv/FSRCNN-TensorFlow/releases/download/1.1/FSRCNNX_x2_8-0-4-1.glsl";
sha256 = "03qv0l3b1bznarlv0jpi4gqg1zg3khsw5cp8pmabg73k0xpcwqix";
meta.license = lib.licenses.mit;
};
SSimDownscaler = pkgs.fetchurl {
url = "https://gist.github.com/igv/36508af3ffc84410fe39761d6969be10/raw/ac09db2c0664150863e85d5a4f9f0106b6443a12/SSimDownscaler.glsl";
sha256 = "1c3fp6llg0n8zdxadsg6g3kcvhqvikalbc9q61zgwvsx8q3d8rph";
meta.license = lib.licenses.lgpl3Plus;
};
KrigBilateral = pkgs.fetchurl {
url = "https://gist.github.com/igv/a015fc885d5c22e6891820ad89555637/raw/c471ef6dcbd3c4a977e1c95dc40944ee38fad08a/KrigBilateral.glsl";
sha256 = "11s0h6i0y3h2nrfp6lax6hzwvjbn93akjr6d61jrmz09zdf1iwmc";
meta.license = lib.licenses.lgpl3Plus;
};
};
gallery-view = pkgs.fetchFromGitHub {
owner = "occivink";
repo = "mpv-gallery-view";
rev = "eca93f9ff2b8716ac750824c9980f6eb766756cf";
sha256 = "01ys2nd166lvcppnrch8ls5n6jhrha2z0jcn9hnfip63gvv2c5gn";
meta.license = lib.licenses.gpl2;
};
cycleShaders = shaders: "cycle-values glsl-shaders ${lib.concatStringsSep " " shaders}";
in
{
programs.mpv = {
# mpv can also be useful without a display (e.g. for encoding)
enable = nixosConfig.sbruder.gui.enable || nixosConfig.sbruder.full;
package = pkgs.wrapMpv
(pkgs.mpv-unwrapped.override {
ffmpeg = pkgs.ffmpeg-full;
vapoursynthSupport = true;
vapoursynth = pkgs.vapoursynth.withPlugins (with pkgs; [
vapoursynth-mvtools
]);
})
{
scripts = with pkgs.mpvScripts; [
pitchcontrol
sponsorblock
];
};
defaultProfiles = [
"gpu-hq" # High quality by default
];
config = {
# Main application font
osd-font = "Iosevka Nerd Font";
# Subtitles (adapted from https://github.com/LightArrowsEXE/dotfiles/blob/75973b6c8493368bbdee6e8e632964045fcf22ec/mpv/.config/mpv/mpv.conf#L76)
sub-bold = true;
sub-border-color = "#ff000000";
sub-border-size = 2.4;
sub-color = "#ffffff";
sub-font = "Gandhi Sans"; # see osd-font
sub-font-size = 50;
sub-shadow-color = "#a0000000";
sub-shadow-offset = 0.75;
sub-use-margins = false;
# Nicer looking vobsub/PGS subtitles
sub-gauss = 0.5;
sub-gray = true;
# Allow higher volumes
volume-max = 150;
# Downmix to stereo by default
audio-channels = "stereo";
# Allow seeking in streamed media
force-seekable = true;
# Enable hardware decoding when avaliable
hwdec = "auto-safe";
# Do not show images only one second
image-display-duration = "inf";
# Not too high quality by default (otherwise too high frame drop)
deband = false;
dither-depth = "auto";
# Lossless screenshots
screenshot-format = "png";
# Use youtube-dls format configuration
ytdl-format = "ytdl";
};
bindings = {
# Audio filter bs2b (for headphones)
"b" = "af toggle bs2b";
# Toggle debanding
"D" = "cycle deband";
# Variable correction of audio pitch when changing speed
"k" = "cycle-values audio-pitch-correction no yes";
# Reverse cycling for audio and video (shift modifier on german keyboard layout)
"'" = "cycle audio down";
"-" = "cycle video down";
# Cycle between audio downmixes
"c" = "cycle-values audio-channels stereo mono auto";
# Cycle between smart scalers (and /dev/null = disabled)
"K" = cycleShaders
((map
(radius: "${mpv-prescalers}/compute/ravu-r${toString radius}.hook")
[
4
3
2
]) ++ [ "/dev/null" ]);
"Alt+k" = cycleShaders
((map
(neurons: "${mpv-prescalers}/compute/nnedi3-nns${toString neurons}-win8x4.hook")
[
256
128
64
32
16
]) ++ [ "/dev/null" ]);
# Toggle pitchcontrol
"Ctrl+p" = "script-message-to pitchcontrol toggle";
# more granular panning
"Alt+left" = "add video-pan-x 0.05";
"Alt+right" = "add video-pan-x -0.05";
"Alt+up" = "add video-pan-y 0.05";
"Alt+down" = "add video-pan-y -0.05";
# sub-delay for fixing 24 empty frames on blu-ray
"Alt+z" = "add sub-delay -1";
"Alt+Z" = "add sub-delay +1";
# sub-delay for fixing exact frame offsets (for signs)
"Ctrl+z" = "add sub-delay -0.04170833333";
"Ctrl+Z" = "add sub-delay +0.04170833333";
# sponsorblock: set segment boundaries
"alt+g" = "script-binding sponsorblock/set_segment";
# Exits with error to not mark the video as watched in ytcc
"Shift+q" = "quit-watch-later 1";
};
profiles =
let
mkVisualiser = width: height: rate: {
lavfi-complex = lib.concatStringsSep ";" [
"[aid1]asplit=4[ao][a1][a2][a3]"
"[a1]avectorscope=m=lissajous:s=${toString (width / 3)}x${toString (height / 2)}:draw=dot:r=${toString rate}[avectorscope]"
"[a2]aresample=44100,showwaves=s=${toString (width / 3 * 2)}x${toString (height / 2)}:mode=p2p:colors=red|lightgreen:r=${toString rate}[showwaves]"
"[a3]showcqt=s=${toString width}x${toString (height / 2)}:axis=0:axis_h=0:r=${toString rate}[showcqt]"
"[showwaves][avectorscope]hstack=shortest=1[top]"
"[top][showcqt]vstack=shortest=1,fps=${toString rate}[vo]"
];
alpha = false;
};
in
{
visualiser = mkVisualiser 1920 1200 30;
visualiser-60 = mkVisualiser 1920 1200 60;
visualiser-1080 = mkVisualiser 1920 1080 30;
visualiser-1080-60 = mkVisualiser 1920 1080 60;
visualiser-2160 = mkVisualiser 3840 2160 30;
visualiser-2160-60 = mkVisualiser 3840 2160 60;
hqencode = {
ovc = "libx264";
ovcopts-add = "crf=18";
oac = "flac";
audio-format = "s16";
};
lq = {
scale = "bicubic_fast";
cscale = "bicubic_fast";
dscale = "bicubic_fast";
};
hq = {
scale = "ewa_lanczossharp";
dscale = "mitchell";
linear-downscaling = "no"; # for KrigBilateral
cscale = "ewa_lanczos";
glsl-shader = [
"${shaders.SSimDownscaler}" # dscale
"${shaders.KrigBilateral}" # cscale
"${shaders.fsrcnnx_x2}" # scale
];
};
interpolate = {
blend-subtitles = true;
video-sync = "display-resample";
interpolation = true;
tscale = "box";
tscale-window = "sphinx";
tscale-radius = 1.0;
tscale-clamp = 0.0;
};
mvinterpolate.vf-add = "vapoursynth=${./mvinterpolate.py}";
# adapted from https://github.com/mpv-player/mpv/issues/4418#issuecomment-368272929
clear-speed.af-add = "scaletempo=stride=18:overlap=.6:search=10";
};
};
xdg.configFile = {
# scripts that are incompatible with home-managers mechanism
"mpv/scripts/lib.disable/gallery.lua".source = "${gallery-view}/scripts/lib.disable/gallery.lua";
"mpv/scripts/playlist-view.lua".source = "${gallery-view}/scripts/playlist-view.lua";
# script options
"mpv/script-opts/playlist_view.conf".text = ''
thumbs_dir=${config.xdg.cacheHome}/thumbnails/mpv
'';
"mpv/script-opts/sponsorblock.conf".text = ''
local_database=no
'';
# make ytdl-hook use yt-dlp
"mpv/script-opts/ytdl_hook.conf".text = ''
ytdl_path=${pkgs.unstable.yt-dlp}/bin/yt-dlp
'';
"mpv/script-opts/stats.conf".text = ''
font=${config.programs.mpv.config.osd-font}
font_mono=${config.programs.mpv.config.osd-font}
font_size=10
redraw_delay=0.25
'';
# mpv-gallery-views thumbnail generation mechanism supports multithreading by linking it multiple times
} // lib.listToAttrs
(map
(i: lib.nameValuePair
"mpv/scripts/gallery-thumbgen-${toString i}.lua"
{ source = "${gallery-view}/scripts/gallery-thumbgen.lua"; })
(lib.range 1 16));
# dummy file
home.file."${config.xdg.cacheHome}/thumbnails/mpv/.create".text = "";
}