[bug#74801,v3] gnu: home: services: Add home-mpv-service-type.

Message ID 3f2fe502b4e02c3c9d2a0890da8ed46b37598ce9.1746786834.git.~@wolfsden.cz
State New
Headers
Series [bug#74801,v3] gnu: home: services: Add home-mpv-service-type. |

Commit Message

Tomas Volf May 9, 2025, 10:33 a.m. UTC
  This commit adds a new service type to generate configuration file for the mpv
media player.

* gnu/home/services/mpv.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Register it.
* doc/guix.texi (mpv Media Player): Document it.

Change-Id: I2deb44799a28047cb5d67da97dc6007a9df873af
---
Originally I attempted to use Guix Records (via define-configuration) for
this, but ran into the bug #74748, so I had to switch to procedures instead.
The usage is (hopefully) sufficiently described in the documentation.  When
the bug is resolved, I will update it to use define-configuration instead.

The full list of supported options is documented, however I decided to *not*
document types and purpose for each individual fields.  While I had mostly
working prototype to extract the documentation from mpv, once I realized it
would be few 10k of lines added, I decided it is not worth it.  It would bloat
the .texi file (by more than 50%), be hard to maintain and, in my opinion,
would not provide enough value to justify that.  The current version seems
like sane middle ground.

Option to configure inputs (for mpv) will come later in a separate patch.

v3:
- Drop majority of commit message.  (I am not sold on this.)
- Use ? suffix for boolean options.
- Include link to the updater script.

 doc/guix.texi             |  429 ++++++
 gnu/home/services/mpv.scm | 2751 +++++++++++++++++++++++++++++++++++++
 gnu/local.mk              |    1 +
 3 files changed, 3181 insertions(+)
 create mode 100644 gnu/home/services/mpv.scm

--
2.49.0
  

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 889eab2ab3..f8cb759948 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -50747,6 +50747,435 @@  Media Home Services
 @end table
 @end deftp

+@c This is ugly, but upstream does *not* capitalize the ``m'' even when
+@c at the beginning of a sentence.  So let us follow the branding.
+@node mpv Media Player
+@subsection mpv Media Player
+
+@cindex mpv, Home Service
+@cindex mpv, configuration
+Configuring the @uref{https://mpv.io/, mpv media player} can be somewhat
+daunting task, due to the sheer amount of options available, especially
+if one wants to be able to inherit the configuration in their code.  The
+@code{home-mpv-service-type} is provided to help with that problem.
+When the service is added to your home environment, file based on the
+passed configuration is generated and placed into the correct location.
+
+Due to the bug #74748, it does not use Guix Records to represent the
+configuration, but uses keyword arguments to achieve similar result.
+Example follows:
+
+@lisp
+(service home-mpv-service-type
+         (make-home-mpv-configuration
+          #:global (make-mpv-profile-configuration
+                    #:fullscreen #t
+                    #:alang '("jpn" "eng"))))
+@end lisp
+
+@defvar home-mpv-service-type
+This is the type of the mpv home service, whose value is a
+@code{home-mpv-configuration} object.
+@end defvar
+
+@deffn {Procedure} make-home-mpv-configuration
+Return a new instance of @code{home-mpv-configuration}.  Available
+keyword arguments are:
+
+@table @asis
+@item @code{inherit} (default: @code{#t})
+Inherit fields from an another instance.
+
+@item @code{global} (default: @code{(make-mpv-profile-configuration)})
+The global configuration preceding all profiles.
+
+@item @code{profiles} (default: @code{()})
+An alist containing configuration for any additional profiles to include
+in the configuration file.
+
+@lisp
+(make-home-mpv-configuration
+ #:profiles `((fullscreen . ,(make-mpv-profile-configuration
+                              #:fullscreen #t))))
+@end lisp
+
+@item @code{extra-config} (default: @code{#f})
+Additional content to include in the configuration file.  It is placed
+at the end of the file.
+
+@end table
+@end deffn
+
+@deffn {Procedure} make-mpv-profile-configuration
+Return a new instance of @code{mpv-profile-configuration}.  As above, it
+also supports the @code{#:inherit} argument.  Additionally it supports
+keyword arguments named after the options of @command{mpv}.  Hence
+@option{--fullscreen} (or @code{fullscreen} in the configuration file)
+becomes @code{#:fullscreen}.
+
+Few options are using their aliases instead.  @option{audio} instead of
+@option{aid}, @option{video} instead of @option{vid}, @option{sub}
+instead of @option{sid}, @option{screenshot-directory} instead of
+@option{screenshot-dir} and @option{watch-later-directory} instead of
+@option{watch-later-dir}.
+
+Valid values for the fields depend on their type.
+
+@table @asis
+@item Flags
+The value should be @code{#f} or @code{#t}.
+
+@item Numerical fields
+Integer and integer64 fields are validated by @code{integer?}, float and
+double fields by @code{real?}.  Ranges are checked when applicable.
+
+@item Aspect
+Same as integer.
+
+@item ByteSize
+Same as integer64.
+
+@item Choice
+The value should be a symbol representing member of the enumeration.  If
+the choice has @samp{or ...} part, it can also be value of that
+alternative type.
+
+@item @var{type} list
+The value should be a list of the @var{type}.
+
+@end table
+
+Other types accept strings, with validation of the values where possible
+(e.g. type @samp{Color} is validated, but type @samp{Audio channels or
+channel map} is not).
+
+The full list of currently supported keyword arguments is below.  For
+the types, allowed values and full description please refer to the
+@command{mpv --list-options} and
+@uref{https://mpv.io/manual/stable/#options, mpv manual}.
+
+Only set fields are outputted to the configuration file.  Accessors are
+provided for every field, returning either their value or a sentinel
+object @code{%unset-value} (from @code{(gnu services configuration)}).
+
+@code{ab-loop-a}, @code{ab-loop-b}, @code{ab-loop-count},
+@code{access-references?}, @code{ad}, @code{ad-lavc-ac3drc},
+@code{ad-lavc-downmix?}, @code{ad-lavc-o}, @code{ad-lavc-threads},
+@code{ad-queue-enable?}, @code{ad-queue-max-bytes},
+@code{ad-queue-max-samples}, @code{ad-queue-max-secs}, @code{af},
+@code{audio}, @code{alang}, @code{allow-delayed-peak-detect?},
+@code{alsa-buffer-time}, @code{alsa-ignore-chmap?},
+@code{alsa-mixer-device}, @code{alsa-mixer-index},
+@code{alsa-mixer-name}, @code{alsa-non-interleaved?},
+@code{alsa-periods}, @code{alsa-resample?}, @code{ao},
+@code{ao-null-broken-delay?}, @code{ao-null-broken-eof?},
+@code{ao-null-buffer}, @code{ao-null-channel-layouts},
+@code{ao-null-format}, @code{ao-null-latency}, @code{ao-null-outburst},
+@code{ao-null-speed}, @code{ao-null-untimed?}, @code{ao-pcm-append?},
+@code{ao-pcm-file}, @code{ao-pcm-waveheader?},
+@code{audio-backward-batch}, @code{audio-backward-overlap},
+@code{audio-buffer}, @code{audio-channels}, @code{audio-client-name},
+@code{audio-delay}, @code{audio-demuxer}, @code{audio-device},
+@code{audio-display}, @code{audio-exclusive?}, @code{audio-exts},
+@code{audio-fallback-to-null?}, @code{audio-file-auto},
+@code{audio-file-paths}, @code{audio-files}, @code{audio-format},
+@code{audio-normalize-downmix?}, @code{audio-pitch-correction?},
+@code{audio-resample-cutoff}, @code{audio-resample-filter-size},
+@code{audio-resample-linear?}, @code{audio-resample-max-output-size},
+@code{audio-resample-phase-shift}, @code{audio-reversal-buffer},
+@code{audio-samplerate}, @code{audio-spdif},
+@code{audio-stream-silence?}, @code{audio-swresample-o},
+@code{audio-wait-open}, @code{auto-window-resize?},
+@code{autocreate-playlist}, @code{autofit}, @code{autofit-larger},
+@code{autofit-smaller}, @code{autoload-files?}, @code{autosync},
+@code{background}, @code{background-color}, @code{blend-subtitles},
+@code{bluray-device}, @code{border?}, @code{border-background},
+@code{brightness}, @code{cache}, @code{cache-on-disk?},
+@code{cache-pause?}, @code{cache-pause-initial?},
+@code{cache-pause-wait}, @code{cache-secs}, @code{cdda-cdtext?},
+@code{cdda-device}, @code{cdda-overlap}, @code{cdda-paranoia},
+@code{cdda-sector-size}, @code{cdda-skip?}, @code{cdda-span-a},
+@code{cdda-span-b}, @code{cdda-speed}, @code{cdda-toc-offset},
+@code{chapter-merge-threshold}, @code{chapter-seek-threshold},
+@code{chapters-file}, @code{config?}, @code{container-fps-override},
+@code{contrast}, @code{cookies?}, @code{cookies-file},
+@code{corner-rounding}, @code{correct-downscaling?},
+@code{correct-pts?}, @code{cover-art-auto}, @code{cover-art-files},
+@code{cover-art-whitelist}, @code{cscale}, @code{cscale-antiring},
+@code{cscale-blur}, @code{cscale-clamp}, @code{cscale-param1},
+@code{cscale-param2}, @code{cscale-radius}, @code{cscale-taper},
+@code{cscale-window}, @code{cscale-wparam}, @code{cscale-wtaper},
+@code{cursor-autohide}, @code{cursor-autohide-fs-only?}, @code{deband?},
+@code{deband-grain}, @code{deband-iterations}, @code{deband-range},
+@code{deband-threshold}, @code{deinterlace},
+@code{deinterlace-field-parity}, @code{demuxer},
+@code{demuxer-backward-playback-step}, @code{demuxer-cache-dir},
+@code{demuxer-cache-unlink-files}, @code{demuxer-cache-wait?},
+@code{demuxer-donate-buffer?}, @code{demuxer-hysteresis-secs},
+@code{demuxer-lavf-allow-mimetype?},
+@code{demuxer-lavf-analyzeduration}, @code{demuxer-lavf-buffersize},
+@code{demuxer-lavf-format}, @code{demuxer-lavf-hacks?},
+@code{demuxer-lavf-linearize-timestamps}, @code{demuxer-lavf-o},
+@code{demuxer-lavf-probe-info}, @code{demuxer-lavf-probescore},
+@code{demuxer-lavf-probesize}, @code{demuxer-lavf-propagate-opts?},
+@code{demuxer-max-back-bytes}, @code{demuxer-max-bytes},
+@code{demuxer-mkv-probe-start-time?},
+@code{demuxer-mkv-probe-video-duration},
+@code{demuxer-mkv-subtitle-preroll},
+@code{demuxer-mkv-subtitle-preroll-secs},
+@code{demuxer-mkv-subtitle-preroll-secs-index},
+@code{demuxer-rawaudio-channels}, @code{demuxer-rawaudio-format},
+@code{demuxer-rawaudio-rate}, @code{demuxer-rawvideo-codec},
+@code{demuxer-rawvideo-format}, @code{demuxer-rawvideo-fps},
+@code{demuxer-rawvideo-h}, @code{demuxer-rawvideo-mp-format},
+@code{demuxer-rawvideo-size}, @code{demuxer-rawvideo-w},
+@code{demuxer-readahead-secs}, @code{demuxer-seekable-cache},
+@code{demuxer-termination-timeout}, @code{demuxer-thread?},
+@code{directory-filter-types}, @code{directory-mode},
+@code{display-fps-override}, @code{display-tags}, @code{dither},
+@code{dither-depth}, @code{dither-size-fruit}, @code{drag-and-drop},
+@code{drm-connector}, @code{drm-device}, @code{drm-draw-plane},
+@code{drm-draw-surface-size}, @code{drm-drmprime-video-plane},
+@code{drm-format}, @code{drm-mode}, @code{drm-vrr-enabled},
+@code{dscale}, @code{dscale-antiring}, @code{dscale-blur},
+@code{dscale-clamp}, @code{dscale-param1}, @code{dscale-param2},
+@code{dscale-radius}, @code{dscale-taper}, @code{dscale-window},
+@code{dscale-wparam}, @code{dscale-wtaper}, @code{dump-stats},
+@code{dvbin-card}, @code{dvbin-channel-switch-offset},
+@code{dvbin-file}, @code{dvbin-full-transponder?}, @code{dvbin-prog},
+@code{dvbin-timeout}, @code{dvd-angle}, @code{dvd-device},
+@code{dvd-speed}, @code{edition}, @code{egl-config-id},
+@code{egl-output-format}, @code{embeddedfonts?}, @code{end},
+@code{error-diffusion}, @code{external-files}, @code{fbo-format},
+@code{focus-on}, @code{force-media-title}, @code{force-render?},
+@code{force-rgba-osd-rendering?}, @code{force-seekable?},
+@code{force-window}, @code{force-window-position?}, @code{framedrop},
+@code{frames}, @code{fs-screen}, @code{fs-screen-name},
+@code{fullscreen?}, @code{gamma}, @code{gamma-auto?},
+@code{gamma-factor}, @code{gamut-mapping-mode}, @code{gapless-audio},
+@code{geometry}, @code{glsl-shader-opts}, @code{glsl-shaders},
+@code{gpu-api}, @code{gpu-context}, @code{gpu-debug?},
+@code{gpu-dumb-mode}, @code{gpu-hwdec-interop},
+@code{gpu-shader-cache?}, @code{gpu-shader-cache-dir}, @code{gpu-sw?},
+@code{gpu-tex-pad-x}, @code{gpu-tex-pad-y}, @code{hdr-compute-peak},
+@code{hdr-contrast-recovery}, @code{hdr-contrast-smoothness},
+@code{hdr-peak-decay-rate}, @code{hdr-peak-percentile},
+@code{hdr-scene-threshold-high}, @code{hdr-scene-threshold-low},
+@code{hidpi-window-scale?}, @code{hls-bitrate}, @code{hr-seek},
+@code{hr-seek-demuxer-offset}, @code{hr-seek-framedrop?},
+@code{http-header-fields}, @code{http-proxy}, @code{hue}, @code{hwdec},
+@code{hwdec-codecs}, @code{hwdec-extra-frames},
+@code{hwdec-image-format}, @code{icc-3dlut-size}, @code{icc-cache?},
+@code{icc-cache-dir}, @code{icc-force-contrast}, @code{icc-intent},
+@code{icc-profile}, @code{icc-profile-auto?}, @code{icc-use-luma?},
+@code{idle}, @code{ignore-path-in-watch-later-config?},
+@code{image-display-duration}, @code{image-exts}, @code{image-lut},
+@code{image-lut-type}, @code{image-subs-video-resolution?},
+@code{include}, @code{index}, @code{initial-audio-sync?},
+@code{input-ar-delay}, @code{input-ar-rate},
+@code{input-builtin-bindings?}, @code{input-builtin-dragging?},
+@code{input-commands}, @code{input-conf}, @code{input-cursor?},
+@code{input-cursor-passthrough?}, @code{input-default-bindings?},
+@code{input-doubleclick-time}, @code{input-dragging-deadzone},
+@code{input-ipc-client}, @code{input-ipc-server},
+@code{input-key-fifo-size}, @code{input-media-keys?},
+@code{input-preprocess-wheel?}, @code{input-right-alt-gr?},
+@code{input-terminal?}, @code{input-test?},
+@code{input-touch-emulate-mouse?}, @code{input-vo-keyboard?},
+@code{interpolation?}, @code{interpolation-preserve?},
+@code{interpolation-threshold}, @code{inverse-tone-mapping?},
+@code{jack-autostart?}, @code{jack-connect?}, @code{jack-name},
+@code{jack-port}, @code{jack-std-channel-layout}, @code{keep-open},
+@code{keep-open-pause?}, @code{keepaspect?}, @code{keepaspect-window?},
+@code{lavfi-complex}, @code{length}, @code{libplacebo-opts},
+@code{linear-downscaling?}, @code{linear-upscaling?},
+@code{load-auto-profiles}, @code{load-osd-console?},
+@code{load-scripts?}, @code{load-select?}, @code{load-stats-overlay?},
+@code{load-unsafe-playlists?}, @code{log-file}, @code{loop-file},
+@code{loop-playlist}, @code{lut}, @code{lut-type}, @code{mc},
+@code{media-controls}, @code{merge-files?}, @code{metadata-codepage},
+@code{mf-fps}, @code{mf-type}, @code{monitoraspect},
+@code{monitorpixelaspect}, @code{msg-color?}, @code{msg-level},
+@code{msg-module?}, @code{msg-time?}, @code{mute?}, @code{native-fs?},
+@code{native-keyrepeat?}, @code{native-touch?}, @code{network-timeout},
+@code{oac}, @code{oacopts}, @code{ocopy-metadata?}, @code{of},
+@code{ofopts}, @code{on-all-workspaces?}, @code{ontop?},
+@code{ontop-level}, @code{opengl-check-pattern-a},
+@code{opengl-check-pattern-b}, @code{opengl-early-flush},
+@code{opengl-es}, @code{opengl-glfinish?}, @code{opengl-pbo?},
+@code{opengl-rectangle-textures?}, @code{opengl-swapinterval},
+@code{opengl-waitvsync?}, @code{orawts?}, @code{ordered-chapters?},
+@code{ordered-chapters-files}, @code{oremove-metadata}, @code{osc?},
+@code{osd-align-x}, @code{osd-align-y}, @code{osd-back-color},
+@code{osd-bar?}, @code{osd-bar-align-x}, @code{osd-bar-align-y},
+@code{osd-bar-h}, @code{osd-bar-outline-size}, @code{osd-bar-w},
+@code{osd-blur}, @code{osd-bold?}, @code{osd-border-style},
+@code{osd-color}, @code{osd-duration}, @code{osd-font},
+@code{osd-font-provider}, @code{osd-font-size}, @code{osd-fonts-dir},
+@code{osd-fractions?}, @code{osd-italic?}, @code{osd-justify},
+@code{osd-level}, @code{osd-margin-x}, @code{osd-margin-y},
+@code{osd-msg1}, @code{osd-msg2}, @code{osd-msg3}, @code{osd-on-seek},
+@code{osd-outline-color}, @code{osd-outline-size},
+@code{osd-playing-msg}, @code{osd-playing-msg-duration},
+@code{osd-playlist-entry}, @code{osd-scale},
+@code{osd-scale-by-window?}, @code{osd-shadow-offset},
+@code{osd-spacing}, @code{osd-status-msg}, @code{oset-metadata},
+@code{ovc}, @code{ovcopts}, @code{panscan}, @code{pause?},
+@code{pipewire-buffer}, @code{pipewire-remote},
+@code{pipewire-volume-mode}, @code{pitch}, @code{play-direction},
+@code{player-operation-mode}, @code{playlist-start},
+@code{prefetch-playlist?}, @code{profile},
+@code{pulse-allow-suspended?}, @code{pulse-buffer}, @code{pulse-host},
+@code{pulse-latency-hacks?}, @code{quiet?}, @code{really-quiet?},
+@code{rebase-start-time?}, @code{referrer}, @code{replaygain},
+@code{replaygain-clip?}, @code{replaygain-fallback},
+@code{replaygain-preamp}, @code{reset-on-next-file},
+@code{resume-playback?}, @code{resume-playback-check-mtime?},
+@code{rtsp-transport}, @code{saturation}, @code{save-position-on-quit?},
+@code{scale}, @code{scale-antiring}, @code{scale-blur},
+@code{scale-clamp}, @code{scale-param1}, @code{scale-param2},
+@code{scale-radius}, @code{scale-taper}, @code{scale-window},
+@code{scale-wparam}, @code{scale-wtaper}, @code{scaler-resizes-only?},
+@code{screen}, @code{screen-name}, @code{screenshot-avif-encoder},
+@code{screenshot-avif-opts}, @code{screenshot-avif-pixfmt},
+@code{screenshot-directory}, @code{screenshot-format},
+@code{screenshot-high-bit-depth?}, @code{screenshot-jpeg-quality},
+@code{screenshot-jpeg-source-chroma?}, @code{screenshot-jxl-distance},
+@code{screenshot-jxl-effort}, @code{screenshot-png-compression},
+@code{screenshot-png-filter}, @code{screenshot-sw?},
+@code{screenshot-tag-colorspace?}, @code{screenshot-template},
+@code{screenshot-webp-compression}, @code{screenshot-webp-lossless?},
+@code{screenshot-webp-quality}, @code{script-opts}, @code{scripts},
+@code{secondary-sid}, @code{secondary-sub-ass-override},
+@code{secondary-sub-delay}, @code{secondary-sub-pos},
+@code{secondary-sub-visibility?}, @code{sharpen},
+@code{show-in-taskbar?}, @code{shuffle?}, @code{sub},
+@code{sigmoid-center}, @code{sigmoid-slope}, @code{sigmoid-upscaling?},
+@code{slang}, @code{snap-window?}, @code{speed}, @code{spirv-compiler},
+@code{sstep}, @code{start}, @code{stop-playback-on-init-failure?},
+@code{stop-screensaver}, @code{stream-buffer-size}, @code{stream-dump},
+@code{stream-lavf-o}, @code{stream-record}, @code{stretch-dvd-subs?},
+@code{stretch-image-subs-to-screen?}, @code{sub-align-x},
+@code{sub-align-y}, @code{sub-ass?}, @code{sub-ass-force-margins?},
+@code{sub-ass-hinting}, @code{sub-ass-justify?},
+@code{sub-ass-line-spacing}, @code{sub-ass-override},
+@code{sub-ass-scale-with-window?}, @code{sub-ass-shaper},
+@code{sub-ass-style-overrides}, @code{sub-ass-styles},
+@code{sub-ass-use-video-data}, @code{sub-ass-video-aspect-override},
+@code{sub-ass-vsfilter-color-compat}, @code{sub-auto},
+@code{sub-auto-exts}, @code{sub-back-color}, @code{sub-blur},
+@code{sub-bold?}, @code{sub-border-style}, @code{sub-clear-on-seek?},
+@code{sub-codepage}, @code{sub-color}, @code{sub-create-cc-track?},
+@code{sub-delay}, @code{sub-demuxer}, @code{sub-file-paths},
+@code{sub-files}, @code{sub-filter-jsre}, @code{sub-filter-regex},
+@code{sub-filter-regex-enable?}, @code{sub-filter-regex-plain?},
+@code{sub-filter-regex-warn?}, @code{sub-filter-sdh?},
+@code{sub-filter-sdh-enclosures}, @code{sub-filter-sdh-harder?},
+@code{sub-fix-timing?}, @code{sub-font}, @code{sub-font-provider},
+@code{sub-font-size}, @code{sub-fonts-dir},
+@code{sub-forced-events-only?}, @code{sub-fps}, @code{sub-gauss},
+@code{sub-gray?}, @code{sub-italic?}, @code{sub-justify},
+@code{sub-lavc-o}, @code{sub-margin-x}, @code{sub-margin-y},
+@code{sub-outline-color}, @code{sub-outline-size},
+@code{sub-past-video-end?}, @code{sub-pos}, @code{sub-scale},
+@code{sub-scale-by-window?}, @code{sub-scale-with-window?},
+@code{sub-shadow-offset}, @code{sub-spacing}, @code{sub-speed},
+@code{sub-stretch-durations?}, @code{sub-use-margins?},
+@code{sub-visibility?}, @code{sub-vsfilter-bidi-compat?},
+@code{subs-fallback}, @code{subs-fallback-forced},
+@code{subs-match-os-language?}, @code{subs-with-matching-audio},
+@code{swapchain-depth}, @code{sws-allow-zimg?}, @code{sws-bitexact?},
+@code{sws-cgb}, @code{sws-chs}, @code{sws-cs}, @code{sws-cvs},
+@code{sws-fast?}, @code{sws-lgb}, @code{sws-ls}, @code{sws-scaler},
+@code{target-colorspace-hint?}, @code{target-contrast},
+@code{target-gamut}, @code{target-lut}, @code{target-peak},
+@code{target-prim}, @code{target-trc}, @code{taskbar-progress?},
+@code{teletext-page}, @code{temporal-dither?},
+@code{temporal-dither-period}, @code{term-osd}, @code{term-osd-bar?},
+@code{term-osd-bar-chars}, @code{term-playing-msg},
+@code{term-status-msg}, @code{term-title}, @code{terminal?},
+@code{title}, @code{title-bar?}, @code{tls-ca-file},
+@code{tls-cert-file}, @code{tls-key-file}, @code{tls-verify?},
+@code{tone-mapping}, @code{tone-mapping-max-boost},
+@code{tone-mapping-param}, @code{tone-mapping-visualize?},
+@code{track-auto-selection?}, @code{tscale}, @code{tscale-antiring},
+@code{tscale-blur}, @code{tscale-clamp}, @code{tscale-param1},
+@code{tscale-param2}, @code{tscale-radius}, @code{tscale-taper},
+@code{tscale-window}, @code{tscale-wparam}, @code{tscale-wtaper},
+@code{untimed?}, @code{use-embedded-icc-profile?},
+@code{use-filedir-conf?}, @code{user-agent}, @code{vaapi-device},
+@code{vd}, @code{vd-apply-cropping?}, @code{vd-lavc-assume-old-x264?},
+@code{vd-lavc-bitexact?}, @code{vd-lavc-check-hw-profile?},
+@code{vd-lavc-dr}, @code{vd-lavc-fast?}, @code{vd-lavc-film-grain},
+@code{vd-lavc-framedrop}, @code{vd-lavc-o}, @code{vd-lavc-show-all?},
+@code{vd-lavc-skipframe}, @code{vd-lavc-skipidct},
+@code{vd-lavc-skiploopfilter}, @code{vd-lavc-software-fallback},
+@code{vd-lavc-threads}, @code{vd-queue-enable?},
+@code{vd-queue-max-bytes}, @code{vd-queue-max-samples},
+@code{vd-queue-max-secs}, @code{vf}, @code{video}, @code{video-align-x},
+@code{video-align-y}, @code{video-aspect-method},
+@code{video-aspect-override}, @code{video-backward-batch},
+@code{video-backward-overlap}, @code{video-crop}, @code{video-exts},
+@code{video-latency-hacks?}, @code{video-margin-ratio-bottom},
+@code{video-margin-ratio-left}, @code{video-margin-ratio-right},
+@code{video-margin-ratio-top}, @code{video-osd?},
+@code{video-output-levels}, @code{video-pan-x}, @code{video-pan-y},
+@code{video-reversal-buffer}, @code{video-rotate}, @code{video-scale-x},
+@code{video-scale-y}, @code{video-sync},
+@code{video-sync-max-audio-change}, @code{video-sync-max-factor},
+@code{video-sync-max-video-change}, @code{video-timing-offset},
+@code{video-unscaled}, @code{video-zoom}, @code{vlang}, @code{vo},
+@code{vo-image-avif-encoder}, @code{vo-image-avif-opts},
+@code{vo-image-avif-pixfmt}, @code{vo-image-format},
+@code{vo-image-high-bit-depth?}, @code{vo-image-jpeg-quality},
+@code{vo-image-jpeg-source-chroma?}, @code{vo-image-jxl-distance},
+@code{vo-image-jxl-effort}, @code{vo-image-outdir},
+@code{vo-image-png-compression}, @code{vo-image-png-filter},
+@code{vo-image-tag-colorspace?}, @code{vo-image-webp-compression},
+@code{vo-image-webp-lossless?}, @code{vo-image-webp-quality},
+@code{vo-kitty-alt-screen?}, @code{vo-kitty-cols},
+@code{vo-kitty-config-clear?}, @code{vo-kitty-height},
+@code{vo-kitty-left}, @code{vo-kitty-rows}, @code{vo-kitty-top},
+@code{vo-kitty-use-shm?}, @code{vo-kitty-width}, @code{vo-null-fps},
+@code{vo-sixel-alt-screen?}, @code{vo-sixel-buffered?},
+@code{vo-sixel-cols}, @code{vo-sixel-config-clear?},
+@code{vo-sixel-dither}, @code{vo-sixel-fixedpalette?},
+@code{vo-sixel-height}, @code{vo-sixel-left}, @code{vo-sixel-pad-x},
+@code{vo-sixel-pad-y}, @code{vo-sixel-reqcolors}, @code{vo-sixel-rows},
+@code{vo-sixel-threshold}, @code{vo-sixel-top}, @code{vo-sixel-width},
+@code{vo-tct-256?}, @code{vo-tct-algo}, @code{vo-tct-buffering},
+@code{vo-tct-height}, @code{vo-tct-width}, @code{vo-vaapi-scaled-osd?},
+@code{vo-vaapi-scaling}, @code{vo-vdpau-chroma-deint?},
+@code{vo-vdpau-colorkey}, @code{vo-vdpau-composite-detect?},
+@code{vo-vdpau-denoise}, @code{vo-vdpau-force-yuv?},
+@code{vo-vdpau-fps}, @code{vo-vdpau-hqscaling},
+@code{vo-vdpau-output-surfaces}, @code{vo-vdpau-pullup?},
+@code{vo-vdpau-queuetime-fs}, @code{vo-vdpau-queuetime-windowed},
+@code{vo-vdpau-sharpen}, @code{volume}, @code{volume-gain},
+@code{volume-gain-max}, @code{volume-gain-min}, @code{volume-max},
+@code{vulkan-async-compute?}, @code{vulkan-async-transfer?},
+@code{vulkan-device}, @code{vulkan-display-display},
+@code{vulkan-display-mode}, @code{vulkan-display-plane},
+@code{vulkan-queue-count}, @code{vulkan-swap-mode},
+@code{watch-later-directory}, @code{watch-later-options},
+@code{wayland-app-id}, @code{wayland-configure-bounds},
+@code{wayland-content-type}, @code{wayland-disable-vsync?},
+@code{wayland-edge-pixels-pointer}, @code{wayland-edge-pixels-touch},
+@code{wayland-present?}, @code{wid}, @code{window-dragging?},
+@code{window-maximized?}, @code{window-minimized?}, @code{window-scale},
+@code{write-filename-in-watch-later-config?},
+@code{x11-bypass-compositor}, @code{x11-name}, @code{x11-netwm},
+@code{x11-present}, @code{x11-wid-title?}, @code{xv-adaptor},
+@code{xv-buffers}, @code{xv-ck}, @code{xv-ck-method},
+@code{xv-colorkey}, @code{xv-port}, @code{ytdl?}, @code{ytdl-format},
+@code{ytdl-raw-options}, @code{zimg-dither}, @code{zimg-fast?},
+@code{zimg-scaler}, @code{zimg-scaler-chroma},
+@code{zimg-scaler-chroma-param-a}, @code{zimg-scaler-chroma-param-b},
+@code{zimg-scaler-param-a}, @code{zimg-scaler-param-b}, and
+@code{zimg-threads}.
+
+@end deffn
+
 @node Sway window manager
 @subsection Sway window manager

diff --git a/gnu/home/services/mpv.scm b/gnu/home/services/mpv.scm
new file mode 100644
index 0000000000..8d11fa03a3
--- /dev/null
+++ b/gnu/home/services/mpv.scm
@@ -0,0 +1,2751 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024, 2025 Tomas Volf <~@wolfsden.cz>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services mpv)
+  #:use-module ((gnu services configuration) #:select (%unset-value
+                                                       maybe-value-set?))
+  #:use-module (gnu home services)
+  #:autoload   (guix diagnostics) (formatted-message)
+  #:autoload   (guix i18n) (G_)
+  #:use-module (guix gexp)
+  #:use-module (ice-9 match)
+  #:use-module (ice-9 regex)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-2)
+  #:use-module (srfi srfi-9)
+  #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-71)
+  #:export (make-home-mpv-configuration
+            home-mpv-configuration?
+            home-mpv-configuration-global
+            home-mpv-configuration-profiles
+            home-mpv-configuration-extra-config
+            home-mpv-configuration-source-location
+
+            serialize-home-mpv-configuration
+
+            make-mpv-profile-configuration
+            mpv-profile-configuration?
+            ;; Field accessor procedures are exported by a syntax form when
+            ;; they are defined, so they are not listed here.
+
+            home-mpv-service-type))
+
+
+;;;
+;;; Basic types.
+;;;
+(define (serialize-mpv/boolean field-name value)
+  #~(string-append (string-trim-right #$(symbol->string field-name) #\?)
+                   "="
+                   #$(if value "yes" "no")
+                   "\n"))
+(define mpv/boolean? boolean?)
+
+(define (serialize-mpv/integer field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(number->string value)
+                   "\n"))
+(define (mpv/integer? n)
+  ;; We assume integer is a signed 32bit number.
+  (and-let* (((integer? n))
+             ((>= n (* -1 (expt 2 (1- 32)))))
+             ((<= n (1-   (expt 2 (1- 32))))))))
+
+(define (serialize-mpv/integer64 field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(number->string value)
+                   "\n"))
+(define (mpv/integer64? n)
+  ;; We assume integer is a signed 64bit number.
+  (and-let* (((integer? n))
+             ((>= n (* -1 (expt 2 (1- 64)))))
+             ((<= n (1-   (expt 2 (1- 64))))))))
+
+(define (serialize-mpv/string field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$value
+                   "\n"))
+(define mpv/string?
+  string?)
+
+(define (serialize-mpv/float field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(number->string (exact->inexact value))
+                   "\n"))
+(define mpv/float?
+  ;; I am not sure how to validate floats.
+  real?)
+
+(define (serialize-mpv/double field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(number->string (exact->inexact value))
+                   "\n"))
+(define mpv/double?
+  ;; I am not sure how to validate doubles.
+  real?)
+
+
+
+
+;;;
+;;; Additional types (possible based on the basic ones).
+;;;
+
+;;; Aspect seems to be treated as an integer, so define it in terms of it.
+(define serialize-mpv/aspect serialize-mpv/integer)
+(define mpv/aspect? mpv/integer?)
+
+;;; `Audio channels or channel map' seems to be basically a free form string
+;;; with no way to validate.
+(define serialize-mpv/audio-channels-or-channel-map serialize-mpv/string)
+(define mpv/audio-channels-or-channel-map? mpv/string?)
+
+;;; Does not seem possible to validate.
+(define serialize-mpv/audio-format serialize-mpv/string)
+(define mpv/audio-format? mpv/string?)
+
+;;; While most options list 4.6116860184274e+18 as a maximum value, we will
+;;; use integer64 here.  That should be enough for everyone for few more
+;;; years.
+(define serialize-mpv/byte-size serialize-mpv/integer64)
+(define mpv/byte-size? mpv/integer64?)
+
+(define (serialize-mpv/color field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(if (list? value)
+                         (string-join (map number->string value) "/")
+                         value)
+                   "\n"))
+(define (mpv/color? value)
+  (define (ok-num? n)
+    (and (number? n)
+         (>= n 0)
+         (<= n 1)))
+  (if (list? value)
+      ;; Either a list of 3(4) numbers encoding RGB(A) on range from 0 to 1...
+      (match value
+        (((? ok-num? r) (? ok-num? g) (? ok-num? b))
+         #t)
+        (((? ok-num? r) (? ok-num? g) (? ok-num? b) (? ok-num? alpha))
+         #t)
+        (_
+         #f))
+      ;; ... or RGB(A) hex encoding.
+      (string-match "^#([A-Fa-f0-9]{2})?[A-Fa-f0-9]{6}$" value)))
+
+;;; I do not see value mirroring fourcc.org's database here.  It is further
+;;; complicated by arbitrary hex being accepted as well.  So string it is.
+(define serialize-mpv/fourcc serialize-mpv/string)
+(define mpv/fourcc? mpv/string?)
+
+;;; No way to validate.
+(define serialize-mpv/image-format serialize-mpv/string)
+(define mpv/image-format? mpv/string?)
+
+;;; Looking at the documentation for --start, there is no way to make this
+;;; bullet-proof, especially since even chapter numbers are accepted.
+(define serialize-mpv/relative-time-or-percent-position serialize-mpv/string)
+(define mpv/relative-time-or-percent-position? mpv/string?)
+
+(define serialize-mpv/time serialize-mpv/string)
+(define mpv/time? mpv/string?)
+
+(define serialize-mpv/video-rectangle serialize-mpv/string)
+(define (mpv/video-rectangle? value)
+  (or (string-match "-?[0-9]+%?:-?[0-9]+%?" value)
+      (string-match
+       "^(-?[0-9]+%?(x-?[0-9]+%?)?)?([+-]-?[0-9]+%?[+-]-?[0-9]+%?)?$"
+       value)))
+
+(define serialize-mpv/window-geometry serialize-mpv/string)
+(define (mpv/window-geometry? value)
+  (or (string-match "-?[0-9]+%?:-?[0-9]+%?" value)
+      (string-match
+       "^(-?[0-9]+%?(x-?[0-9]+%?)?)?([+-]-?[0-9]+%?[+-]-?[0-9]+%?)?(/[0-9]+)?$"
+       value)))
+
+(define serialize-mpv/window-size serialize-mpv/string)
+(define (mpv/window-size? value)
+  (string-match "^([0-9]+%?(x[0-9]+%?)?)?$" value))
+
+(define (serialize-mpv/enumeration field-name value)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   ;; This could be either symbol or (in case of enumerations
+                   ;; with alternate type) anything.  So just use `format'.
+                   #$(format #f "~s" value)
+                   "\n"))
+(define (mpv/enumeration? value)
+  ;; There is no general way to check enumerations.  The field always has to
+  ;; define custom sanitizer.
+  #t)
+
+
+
+
+;;;
+;;; List types.
+;;;
+(define (serialize-mpv/list-of-string field-name lst)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(string-join lst ",")
+                   "\n"))
+(define (mpv/list-of-string? lst)
+  (every mpv/string? lst))
+
+(define (serialize-mpv/list-of-key-value field-name lst)
+  #~(string-append #$(symbol->string field-name)
+                   "="
+                   #$(string-join (map (match-lambda
+                                         ((k . v) (format #f "~a=~a" k v)))
+                                       lst)
+                                  ",")
+                   "\n"))
+(define (mpv/list-of-key-value? lst)
+  (every (match-lambda
+           (((? string?) . (? string?)) #t)
+           (_ #f))
+         lst))
+
+(define serialize-mpv/list-of-object-setting serialize-mpv/list-of-string)
+(define mpv/list-of-object-setting? mpv/list-of-string?)
+
+(define serialize-mpv/list-of-output-verbosity serialize-mpv/list-of-key-value)
+(define mpv/list-of-output-verbosity? mpv/list-of-key-value?)
+
+
+
+
+;;;
+;;; Actual configuration record.  Contains a lot of generated code.
+;;;
+
+(define-record-type <profile-option>
+  (make-profile-option name type-check serializer)
+  profile-option?
+  (name       profile-option-name)
+  (type-check profile-option-type-check)
+  (serializer profile-option-serializer))
+
+(define %opts (make-hash-table))
+
+(define-syntax define-opt
+  (lambda (x)
+    (syntax-case x ()
+      ((_ name type extra-checks ...)
+       (let* ((d/n (syntax->datum #'name))
+              (d/t (syntax->datum #'type))
+              (d/accessor (string->symbol
+                           (format #f "mpv-profile-configuration-~a" d/n)))
+              (d/type-check (string->symbol
+                             (format #f "mpv/~a?" d/t)))
+              (d/serializer (string->symbol
+                             (format #f "serialize-mpv/~a" d/t))))
+         (with-syntax
+             ((kw (datum->syntax x (symbol->keyword d/n)))
+              (accessor (datum->syntax x d/accessor))
+              (type-check (datum->syntax x d/type-check))
+              (serializer (datum->syntax x d/serializer))
+              (val (datum->syntax x 'val)))
+           #'(begin
+               (hashq-set! %opts 'name
+                           (make-profile-option (symbol->string 'name)
+                                                (lambda (val)
+                                                  (and (type-check val)
+                                                       extra-checks ...))
+                                                serializer))
+               (define-public (accessor cfg)
+                 (let ((x (hashq-ref (%mpv-profile-configuration-data cfg)
+                                     'name
+                                     %unset-value)))
+                   (if (eq? x %unset-value)
+                       %unset-value
+                       (car x)))))))))))
+
+;;; Generated by: https://git.wolfsden.cz/guix/tree/etc/update-mpv-configuration
+;;; Generated code - START.
+(define-opt ab-loop-a time)
+(define-opt ab-loop-b time)
+(define-opt
+  ab-loop-count
+  enumeration
+  (or (memq val '(inf))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt access-references? boolean)
+(define-opt ad string)
+(define-opt
+  ad-lavc-ac3drc
+  float
+  (>= val 0)
+  (<= val 6))
+(define-opt ad-lavc-downmix? boolean)
+(define-opt ad-lavc-o list-of-key-value)
+(define-opt
+  ad-lavc-threads
+  integer
+  (>= val 0)
+  (<= val 16))
+(define-opt ad-queue-enable? boolean)
+(define-opt
+  ad-queue-max-bytes
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  ad-queue-max-samples
+  integer64
+  (>= val 0))
+(define-opt ad-queue-max-secs double (>= val 0))
+(define-opt af list-of-object-setting)
+(define-opt
+  audio
+  enumeration
+  (or (memq val '(no auto))
+      (and (integer? val) (>= val 0) (<= val 8190))))
+(define-opt alang list-of-string)
+(define-opt allow-delayed-peak-detect? boolean)
+(define-opt
+  alsa-buffer-time
+  integer
+  (>= val 0)
+  (<= val 2147483647))
+(define-opt alsa-ignore-chmap? boolean)
+(define-opt alsa-mixer-device string)
+(define-opt
+  alsa-mixer-index
+  integer
+  (>= val 0)
+  (<= val 99))
+(define-opt alsa-mixer-name string)
+(define-opt alsa-non-interleaved? boolean)
+(define-opt
+  alsa-periods
+  integer
+  (>= val 0)
+  (<= val 2147483647))
+(define-opt alsa-resample? boolean)
+(define-opt ao list-of-object-setting)
+(define-opt ao-null-broken-delay? boolean)
+(define-opt ao-null-broken-eof? boolean)
+(define-opt
+  ao-null-buffer
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt
+  ao-null-channel-layouts
+  audio-channels-or-channel-map)
+(define-opt ao-null-format audio-format)
+(define-opt
+  ao-null-latency
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt
+  ao-null-outburst
+  integer
+  (>= val 1)
+  (<= val 100000))
+(define-opt
+  ao-null-speed
+  float
+  (>= val 0)
+  (<= val 10000))
+(define-opt ao-null-untimed? boolean)
+(define-opt ao-pcm-append? boolean)
+(define-opt ao-pcm-file string)
+(define-opt ao-pcm-waveheader? boolean)
+(define-opt
+  audio-backward-batch
+  integer
+  (>= val 0)
+  (<= val 1024))
+(define-opt
+  audio-backward-overlap
+  enumeration
+  (or (memq val '(auto))
+      (and (integer? val) (>= val 0) (<= val 1024))))
+(define-opt
+  audio-buffer
+  double
+  (>= val 0)
+  (<= val 10))
+(define-opt
+  audio-channels
+  audio-channels-or-channel-map)
+(define-opt audio-client-name string)
+(define-opt audio-delay float)
+(define-opt audio-demuxer string)
+(define-opt audio-device string)
+(define-opt
+  audio-display
+  enumeration
+  (memq val '(no embedded-first external-first)))
+(define-opt audio-exclusive? boolean)
+(define-opt audio-exts list-of-string)
+(define-opt audio-fallback-to-null? boolean)
+(define-opt
+  audio-file-auto
+  enumeration
+  (memq val '(no exact fuzzy all)))
+(define-opt audio-file-paths list-of-string)
+(define-opt audio-files list-of-string)
+(define-opt audio-format audio-format)
+(define-opt audio-normalize-downmix? boolean)
+(define-opt audio-pitch-correction? boolean)
+(define-opt
+  audio-resample-cutoff
+  double
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  audio-resample-filter-size
+  integer
+  (>= val 0)
+  (<= val 32))
+(define-opt audio-resample-linear? boolean)
+(define-opt
+  audio-resample-max-output-size
+  double)
+(define-opt
+  audio-resample-phase-shift
+  integer
+  (>= val 0)
+  (<= val 30))
+(define-opt
+  audio-reversal-buffer
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  audio-samplerate
+  integer
+  (>= val 0)
+  (<= val 768000))
+(define-opt audio-spdif string)
+(define-opt audio-stream-silence? boolean)
+(define-opt audio-swresample-o list-of-key-value)
+(define-opt
+  audio-wait-open
+  float
+  (>= val 0)
+  (<= val 60))
+(define-opt auto-window-resize? boolean)
+(define-opt
+  autocreate-playlist
+  enumeration
+  (memq val '(no filter same)))
+(define-opt autofit window-size)
+(define-opt autofit-larger window-size)
+(define-opt autofit-smaller window-size)
+(define-opt autoload-files? boolean)
+(define-opt
+  autosync
+  enumeration
+  (or (memq val '(no))
+      (and (integer? val) (>= val 0) (<= val 10000))))
+(define-opt
+  background
+  enumeration
+  (memq val '(none color tiles)))
+(define-opt background-color color)
+(define-opt
+  blend-subtitles
+  enumeration
+  (memq val '(no yes video)))
+(define-opt bluray-device string)
+(define-opt border? boolean)
+(define-opt
+  border-background
+  enumeration
+  (memq val '(none color tiles)))
+(define-opt
+  brightness
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt
+  cache
+  enumeration
+  (memq val '(no auto yes)))
+(define-opt cache-on-disk? boolean)
+(define-opt cache-pause? boolean)
+(define-opt cache-pause-initial? boolean)
+(define-opt cache-pause-wait float (>= val 0))
+(define-opt cache-secs double (>= val 0))
+(define-opt cdda-cdtext? boolean)
+(define-opt cdda-device string)
+(define-opt
+  cdda-overlap
+  integer
+  (>= val 0)
+  (<= val 75))
+(define-opt
+  cdda-paranoia
+  integer
+  (>= val 0)
+  (<= val 2))
+(define-opt
+  cdda-sector-size
+  integer
+  (>= val 1)
+  (<= val 100))
+(define-opt cdda-skip? boolean)
+(define-opt cdda-span-a integer)
+(define-opt cdda-span-b integer)
+(define-opt
+  cdda-speed
+  integer
+  (>= val 1)
+  (<= val 100))
+(define-opt cdda-toc-offset integer)
+(define-opt
+  chapter-merge-threshold
+  integer
+  (>= val 0)
+  (<= val 10000))
+(define-opt chapter-seek-threshold double)
+(define-opt chapters-file string)
+(define-opt config? boolean)
+(define-opt
+  container-fps-override
+  double
+  (>= val 0))
+(define-opt
+  contrast
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt cookies? boolean)
+(define-opt cookies-file string)
+(define-opt
+  corner-rounding
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt correct-downscaling? boolean)
+(define-opt correct-pts? boolean)
+(define-opt
+  cover-art-auto
+  enumeration
+  (memq val '(no exact fuzzy all)))
+(define-opt cover-art-files list-of-string)
+(define-opt cover-art-whitelist list-of-string)
+(define-opt
+  cscale
+  enumeration
+  (memq val
+        '(bilinear
+          bicubic_fast
+          oversample
+          spline16
+          spline36
+          spline64
+          sinc
+          lanczos
+          ginseng
+          bicubic
+          hermite
+          catmull_rom
+          mitchell
+          robidoux
+          robidouxsharp
+          box
+          nearest
+          triangle
+          gaussian
+          jinc
+          ewa_lanczos
+          ewa_hanning
+          ewa_ginseng
+          ewa_lanczossharp
+          ewa_lanczos4sharpest
+          ewa_lanczossoft
+          haasnsoft
+          ewa_robidoux
+          ewa_robidouxsharp
+          bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx)))
+(define-opt
+  cscale-antiring
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt cscale-blur float)
+(define-opt
+  cscale-clamp
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt cscale-param1 float)
+(define-opt cscale-param2 float)
+(define-opt
+  cscale-radius
+  float
+  (>= val 0.5)
+  (<= val 16))
+(define-opt
+  cscale-taper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  cscale-window
+  enumeration
+  (memq val
+        '(bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx
+          jinc)))
+(define-opt cscale-wparam float)
+(define-opt
+  cscale-wtaper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  cursor-autohide
+  enumeration
+  (or (memq val '(no always))
+      (and (integer? val) (>= val 0) (<= val 30000))))
+(define-opt cursor-autohide-fs-only? boolean)
+(define-opt deband? boolean)
+(define-opt
+  deband-grain
+  float
+  (>= val 0)
+  (<= val 4096))
+(define-opt
+  deband-iterations
+  integer
+  (>= val 0)
+  (<= val 16))
+(define-opt
+  deband-range
+  float
+  (>= val 1)
+  (<= val 64))
+(define-opt
+  deband-threshold
+  float
+  (>= val 0)
+  (<= val 4096))
+(define-opt
+  deinterlace
+  enumeration
+  (memq val '(no yes auto)))
+(define-opt
+  deinterlace-field-parity
+  enumeration
+  (memq val '(tff bff auto)))
+(define-opt demuxer string)
+(define-opt
+  demuxer-backward-playback-step
+  double
+  (>= val 0))
+(define-opt demuxer-cache-dir string)
+(define-opt
+  demuxer-cache-unlink-files
+  enumeration
+  (memq val '(immediate whendone no)))
+(define-opt demuxer-cache-wait? boolean)
+(define-opt demuxer-donate-buffer? boolean)
+(define-opt
+  demuxer-hysteresis-secs
+  double
+  (>= val 0))
+(define-opt demuxer-lavf-allow-mimetype? boolean)
+(define-opt
+  demuxer-lavf-analyzeduration
+  float
+  (>= val 0)
+  (<= val 3600))
+(define-opt
+  demuxer-lavf-buffersize
+  integer
+  (>= val 1)
+  (<= val 10485760))
+(define-opt demuxer-lavf-format string)
+(define-opt demuxer-lavf-hacks? boolean)
+(define-opt
+  demuxer-lavf-linearize-timestamps
+  enumeration
+  (memq val '(no auto yes)))
+(define-opt demuxer-lavf-o list-of-key-value)
+(define-opt
+  demuxer-lavf-probe-info
+  enumeration
+  (memq val '(no yes auto nostreams)))
+(define-opt
+  demuxer-lavf-probescore
+  integer
+  (>= val 1)
+  (<= val 100))
+(define-opt
+  demuxer-lavf-probesize
+  integer
+  (>= val 32)
+  (<= val 2147483647))
+(define-opt demuxer-lavf-propagate-opts? boolean)
+(define-opt
+  demuxer-max-back-bytes
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  demuxer-max-bytes
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  demuxer-mkv-probe-start-time?
+  boolean)
+(define-opt
+  demuxer-mkv-probe-video-duration
+  enumeration
+  (memq val '(no yes full)))
+(define-opt
+  demuxer-mkv-subtitle-preroll
+  enumeration
+  (memq val '(no yes index)))
+(define-opt
+  demuxer-mkv-subtitle-preroll-secs
+  double
+  (>= val 0))
+(define-opt
+  demuxer-mkv-subtitle-preroll-secs-index
+  double
+  (>= val 0))
+(define-opt
+  demuxer-rawaudio-channels
+  audio-channels-or-channel-map)
+(define-opt
+  demuxer-rawaudio-format
+  enumeration
+  (memq val
+        '(u8 s8
+             u16le
+             u16be
+             s16le
+             s16be
+             u24le
+             u24be
+             s24le
+             s24be
+             u32le
+             u32be
+             s32le
+             s32be
+             floatle
+             floatbe
+             doublele
+             doublebe
+             u16
+             s16
+             u24
+             s24
+             u32
+             s32
+             float
+             double)))
+(define-opt
+  demuxer-rawaudio-rate
+  integer
+  (>= val 1000)
+  (<= val 384000))
+(define-opt demuxer-rawvideo-codec string)
+(define-opt demuxer-rawvideo-format fourcc)
+(define-opt
+  demuxer-rawvideo-fps
+  float
+  (>= val 0.001)
+  (<= val 1000))
+(define-opt
+  demuxer-rawvideo-h
+  integer
+  (>= val 1)
+  (<= val 8192))
+(define-opt
+  demuxer-rawvideo-mp-format
+  image-format)
+(define-opt
+  demuxer-rawvideo-size
+  integer
+  (>= val 1)
+  (<= val 268435456))
+(define-opt
+  demuxer-rawvideo-w
+  integer
+  (>= val 1)
+  (<= val 8192))
+(define-opt
+  demuxer-readahead-secs
+  double
+  (>= val 0))
+(define-opt
+  demuxer-seekable-cache
+  enumeration
+  (memq val '(auto no yes)))
+(define-opt demuxer-termination-timeout double)
+(define-opt demuxer-thread? boolean)
+(define-opt
+  directory-filter-types
+  list-of-string)
+(define-opt
+  directory-mode
+  enumeration
+  (memq val '(auto lazy recursive ignore)))
+(define-opt
+  display-fps-override
+  double
+  (>= val 0))
+(define-opt display-tags list-of-string)
+(define-opt
+  dither
+  enumeration
+  (memq val '(fruit ordered error-diffusion no)))
+(define-opt
+  dither-depth
+  enumeration
+  (or (memq val '(no auto))
+      (and (integer? val) (>= val -1) (<= val 16))))
+(define-opt
+  dither-size-fruit
+  integer
+  (>= val 2)
+  (<= val 8))
+(define-opt
+  drag-and-drop
+  enumeration
+  (memq val '(no auto replace append insert-next)))
+(define-opt drm-connector string)
+(define-opt drm-device string)
+(define-opt
+  drm-draw-plane
+  enumeration
+  (or (memq val '(primary overlay))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt drm-draw-surface-size window-size)
+(define-opt
+  drm-drmprime-video-plane
+  enumeration
+  (or (memq val '(primary overlay))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt
+  drm-format
+  enumeration
+  (memq val
+        '(xrgb8888 xrgb2101010 xbgr8888 xbgr2101010 yuyv)))
+(define-opt drm-mode string)
+(define-opt
+  drm-vrr-enabled
+  enumeration
+  (memq val '(no yes auto)))
+(define-opt
+  dscale
+  enumeration
+  (memq val
+        '(bilinear
+          bicubic_fast
+          oversample
+          spline16
+          spline36
+          spline64
+          sinc
+          lanczos
+          ginseng
+          bicubic
+          hermite
+          catmull_rom
+          mitchell
+          robidoux
+          robidouxsharp
+          box
+          nearest
+          triangle
+          gaussian
+          jinc
+          ewa_lanczos
+          ewa_hanning
+          ewa_ginseng
+          ewa_lanczossharp
+          ewa_lanczos4sharpest
+          ewa_lanczossoft
+          haasnsoft
+          ewa_robidoux
+          ewa_robidouxsharp
+          bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx)))
+(define-opt
+  dscale-antiring
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt dscale-blur float)
+(define-opt
+  dscale-clamp
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt dscale-param1 float)
+(define-opt dscale-param2 float)
+(define-opt
+  dscale-radius
+  float
+  (>= val 0.5)
+  (<= val 16))
+(define-opt
+  dscale-taper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  dscale-window
+  enumeration
+  (memq val
+        '(bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx
+          jinc)))
+(define-opt dscale-wparam float)
+(define-opt
+  dscale-wtaper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt dump-stats string)
+(define-opt
+  dvbin-card
+  integer
+  (>= val 0)
+  (<= val 15))
+(define-opt dvbin-channel-switch-offset integer)
+(define-opt dvbin-file string)
+(define-opt dvbin-full-transponder? boolean)
+(define-opt dvbin-prog string)
+(define-opt
+  dvbin-timeout
+  integer
+  (>= val 1)
+  (<= val 30))
+(define-opt
+  dvd-angle
+  integer
+  (>= val 1)
+  (<= val 99))
+(define-opt dvd-device string)
+(define-opt dvd-speed integer)
+(define-opt
+  edition
+  enumeration
+  (or (memq val '(auto))
+      (and (integer? val) (>= val 0) (<= val 8190))))
+(define-opt egl-config-id integer)
+(define-opt
+  egl-output-format
+  enumeration
+  (memq val
+        '(auto rgb8
+               rgba8
+               rgb10
+               rgb10_a2
+               rgb16
+               rgba16
+               rgb16f
+               rgba16f
+               rgb32f
+               rgba32f)))
+(define-opt embeddedfonts? boolean)
+(define-opt
+  end
+  relative-time-or-percent-position)
+(define-opt error-diffusion string)
+(define-opt external-files list-of-string)
+(define-opt fbo-format string)
+(define-opt
+  focus-on
+  enumeration
+  (memq val '(never open all)))
+(define-opt force-media-title string)
+(define-opt force-render? boolean)
+(define-opt force-rgba-osd-rendering? boolean)
+(define-opt force-seekable? boolean)
+(define-opt
+  force-window
+  enumeration
+  (memq val '(no yes immediate)))
+(define-opt force-window-position? boolean)
+(define-opt
+  framedrop
+  enumeration
+  (memq val '(no vo decoder decoder+vo)))
+(define-opt
+  frames
+  enumeration
+  (or (memq val '(all))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt
+  fs-screen
+  enumeration
+  (or (memq val '(all current))
+      (and (integer? val) (>= val 0) (<= val 32))))
+(define-opt fs-screen-name string)
+(define-opt fullscreen? boolean)
+(define-opt
+  gamma
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt gamma-auto? boolean)
+(define-opt
+  gamma-factor
+  float
+  (>= val 0.1)
+  (<= val 2))
+(define-opt
+  gamut-mapping-mode
+  enumeration
+  (memq val
+        '(auto clip
+               perceptual
+               relative
+               saturation
+               absolute
+               desaturate
+               darken
+               warn
+               linear)))
+(define-opt
+  gapless-audio
+  enumeration
+  (memq val '(no yes weak)))
+(define-opt geometry window-geometry)
+(define-opt glsl-shader-opts list-of-key-value)
+(define-opt glsl-shaders list-of-string)
+(define-opt gpu-api list-of-object-setting)
+(define-opt gpu-context list-of-object-setting)
+(define-opt gpu-debug? boolean)
+(define-opt
+  gpu-dumb-mode
+  enumeration
+  (memq val '(auto yes no)))
+(define-opt gpu-hwdec-interop string)
+(define-opt gpu-shader-cache? boolean)
+(define-opt gpu-shader-cache-dir string)
+(define-opt gpu-sw? boolean)
+(define-opt
+  gpu-tex-pad-x
+  integer
+  (>= val 0)
+  (<= val 4096))
+(define-opt
+  gpu-tex-pad-y
+  integer
+  (>= val 0)
+  (<= val 4096))
+(define-opt
+  hdr-compute-peak
+  enumeration
+  (memq val '(auto yes no)))
+(define-opt
+  hdr-contrast-recovery
+  float
+  (>= val 0)
+  (<= val 2))
+(define-opt
+  hdr-contrast-smoothness
+  float
+  (>= val 1)
+  (<= val 100))
+(define-opt
+  hdr-peak-decay-rate
+  float
+  (>= val 0)
+  (<= val 1000))
+(define-opt
+  hdr-peak-percentile
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt
+  hdr-scene-threshold-high
+  float
+  (>= val 0)
+  (<= val 20))
+(define-opt
+  hdr-scene-threshold-low
+  float
+  (>= val 0)
+  (<= val 20))
+(define-opt hidpi-window-scale? boolean)
+(define-opt
+  hls-bitrate
+  enumeration
+  (or (memq val '(no min max))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt
+  hr-seek
+  enumeration
+  (memq val '(no absolute yes always default)))
+(define-opt hr-seek-demuxer-offset float)
+(define-opt hr-seek-framedrop? boolean)
+(define-opt http-header-fields list-of-string)
+(define-opt http-proxy string)
+(define-opt hue float (>= val -100) (<= val 100))
+(define-opt hwdec list-of-string)
+(define-opt hwdec-codecs string)
+(define-opt
+  hwdec-extra-frames
+  integer
+  (>= val 0)
+  (<= val 256))
+(define-opt hwdec-image-format image-format)
+(define-opt icc-3dlut-size string)
+(define-opt icc-cache? boolean)
+(define-opt icc-cache-dir string)
+(define-opt
+  icc-force-contrast
+  enumeration
+  (or (memq val '(no inf))
+      (and (integer? val) (>= val 0) (<= val 1000000))))
+(define-opt icc-intent integer)
+(define-opt icc-profile string)
+(define-opt icc-profile-auto? boolean)
+(define-opt icc-use-luma? boolean)
+(define-opt
+  idle
+  enumeration
+  (memq val '(no once yes)))
+(define-opt
+  ignore-path-in-watch-later-config?
+  boolean)
+(define-opt
+  image-display-duration
+  double
+  (>= val 0))
+(define-opt image-exts list-of-string)
+(define-opt image-lut string)
+(define-opt
+  image-lut-type
+  enumeration
+  (memq val '(auto native normalized conversion)))
+(define-opt image-subs-video-resolution? boolean)
+(define-opt include string)
+(define-opt
+  index
+  enumeration
+  (memq val '(default recreate)))
+(define-opt initial-audio-sync? boolean)
+(define-opt input-ar-delay integer)
+(define-opt input-ar-rate integer)
+(define-opt input-builtin-bindings? boolean)
+(define-opt input-builtin-dragging? boolean)
+(define-opt input-commands list-of-string)
+(define-opt input-conf string)
+(define-opt input-cursor? boolean)
+(define-opt input-cursor-passthrough? boolean)
+(define-opt input-default-bindings? boolean)
+(define-opt
+  input-doubleclick-time
+  integer
+  (>= val 0)
+  (<= val 1000))
+(define-opt input-dragging-deadzone integer)
+(define-opt input-ipc-client string)
+(define-opt input-ipc-server string)
+(define-opt
+  input-key-fifo-size
+  integer
+  (>= val 2)
+  (<= val 65000))
+(define-opt input-media-keys? boolean)
+(define-opt input-preprocess-wheel? boolean)
+(define-opt input-right-alt-gr? boolean)
+(define-opt input-terminal? boolean)
+(define-opt input-test? boolean)
+(define-opt input-touch-emulate-mouse? boolean)
+(define-opt input-vo-keyboard? boolean)
+(define-opt interpolation? boolean)
+(define-opt interpolation-preserve? boolean)
+(define-opt interpolation-threshold float)
+(define-opt inverse-tone-mapping? boolean)
+(define-opt jack-autostart? boolean)
+(define-opt jack-connect? boolean)
+(define-opt jack-name string)
+(define-opt jack-port string)
+(define-opt
+  jack-std-channel-layout
+  enumeration
+  (memq val '(waveext any)))
+(define-opt
+  keep-open
+  enumeration
+  (memq val '(no yes always)))
+(define-opt keep-open-pause? boolean)
+(define-opt keepaspect? boolean)
+(define-opt keepaspect-window? boolean)
+(define-opt lavfi-complex string)
+(define-opt
+  length
+  relative-time-or-percent-position)
+(define-opt libplacebo-opts list-of-key-value)
+(define-opt linear-downscaling? boolean)
+(define-opt linear-upscaling? boolean)
+(define-opt
+  load-auto-profiles
+  enumeration
+  (memq val '(no yes auto)))
+(define-opt load-osd-console? boolean)
+(define-opt load-scripts? boolean)
+(define-opt load-select? boolean)
+(define-opt load-stats-overlay? boolean)
+(define-opt load-unsafe-playlists? boolean)
+(define-opt log-file string)
+(define-opt
+  loop-file
+  enumeration
+  (or (memq val '(no inf yes))
+      (and (integer? val) (>= val 0) (<= val 10000))))
+(define-opt
+  loop-playlist
+  enumeration
+  (or (memq val '(no inf yes force))
+      (and (integer? val) (>= val 1) (<= val 10000))))
+(define-opt lut string)
+(define-opt
+  lut-type
+  enumeration
+  (memq val '(auto native normalized conversion)))
+(define-opt mc float (>= val 0) (<= val 100))
+(define-opt
+  media-controls
+  enumeration
+  (memq val '(no player yes)))
+(define-opt merge-files? boolean)
+(define-opt metadata-codepage string)
+(define-opt mf-fps double)
+(define-opt mf-type string)
+(define-opt
+  monitoraspect
+  float
+  (>= val 0)
+  (<= val 9))
+(define-opt
+  monitorpixelaspect
+  float
+  (>= val 0.03125)
+  (<= val 32))
+(define-opt msg-color? boolean)
+(define-opt msg-level list-of-output-verbosity)
+(define-opt msg-module? boolean)
+(define-opt msg-time? boolean)
+(define-opt mute? boolean)
+(define-opt native-fs? boolean)
+(define-opt native-keyrepeat? boolean)
+(define-opt native-touch? boolean)
+(define-opt network-timeout double (>= val 0))
+(define-opt oac string)
+(define-opt oacopts list-of-key-value)
+(define-opt ocopy-metadata? boolean)
+(define-opt of string)
+(define-opt ofopts list-of-key-value)
+(define-opt on-all-workspaces? boolean)
+(define-opt ontop? boolean)
+(define-opt
+  ontop-level
+  enumeration
+  (or (memq val '(window system desktop))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt opengl-check-pattern-a integer)
+(define-opt opengl-check-pattern-b integer)
+(define-opt
+  opengl-early-flush
+  enumeration
+  (memq val '(no yes auto)))
+(define-opt
+  opengl-es
+  enumeration
+  (memq val '(auto yes no)))
+(define-opt opengl-glfinish? boolean)
+(define-opt opengl-pbo? boolean)
+(define-opt opengl-rectangle-textures? boolean)
+(define-opt opengl-swapinterval integer)
+(define-opt opengl-waitvsync? boolean)
+(define-opt orawts? boolean)
+(define-opt ordered-chapters? boolean)
+(define-opt ordered-chapters-files string)
+(define-opt oremove-metadata list-of-string)
+(define-opt osc? boolean)
+(define-opt
+  osd-align-x
+  enumeration
+  (memq val '(left center right)))
+(define-opt
+  osd-align-y
+  enumeration
+  (memq val '(top center bottom)))
+(define-opt osd-back-color color)
+(define-opt osd-bar? boolean)
+(define-opt
+  osd-bar-align-x
+  float
+  (>= val -1)
+  (<= val 1))
+(define-opt
+  osd-bar-align-y
+  float
+  (>= val -1)
+  (<= val 1))
+(define-opt
+  osd-bar-h
+  float
+  (>= val 0.1)
+  (<= val 50))
+(define-opt
+  osd-bar-outline-size
+  float
+  (>= val 0)
+  (<= val 1000))
+(define-opt
+  osd-bar-w
+  float
+  (>= val 1)
+  (<= val 100))
+(define-opt
+  osd-blur
+  float
+  (>= val 0)
+  (<= val 20))
+(define-opt osd-bold? boolean)
+(define-opt
+  osd-border-style
+  enumeration
+  (memq val
+        '(outline-and-shadow opaque-box background-box)))
+(define-opt osd-color color)
+(define-opt
+  osd-duration
+  integer
+  (>= val 0)
+  (<= val 3600000))
+(define-opt osd-font string)
+(define-opt
+  osd-font-provider
+  enumeration
+  (memq val '(auto none fontconfig)))
+(define-opt
+  osd-font-size
+  float
+  (>= val 1)
+  (<= val 9000))
+(define-opt osd-fonts-dir string)
+(define-opt osd-fractions? boolean)
+(define-opt osd-italic? boolean)
+(define-opt
+  osd-justify
+  enumeration
+  (memq val '(auto left center right)))
+(define-opt
+  osd-level
+  enumeration
+  (memq val '(#{0}# #{1}# #{2}# #{3}#)))
+(define-opt
+  osd-margin-x
+  integer
+  (>= val 0)
+  (<= val 300))
+(define-opt
+  osd-margin-y
+  integer
+  (>= val 0)
+  (<= val 600))
+(define-opt osd-msg1 string)
+(define-opt osd-msg2 string)
+(define-opt osd-msg3 string)
+(define-opt
+  osd-on-seek
+  enumeration
+  (memq val '(no bar msg msg-bar)))
+(define-opt osd-outline-color color)
+(define-opt osd-outline-size float)
+(define-opt osd-playing-msg string)
+(define-opt
+  osd-playing-msg-duration
+  integer
+  (>= val 0)
+  (<= val 3600000))
+(define-opt
+  osd-playlist-entry
+  enumeration
+  (memq val '(title filename both)))
+(define-opt
+  osd-scale
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt osd-scale-by-window? boolean)
+(define-opt osd-shadow-offset float)
+(define-opt
+  osd-spacing
+  float
+  (>= val -10)
+  (<= val 10))
+(define-opt osd-status-msg string)
+(define-opt oset-metadata list-of-key-value)
+(define-opt ovc string)
+(define-opt ovcopts list-of-key-value)
+(define-opt panscan float (>= val 0) (<= val 1))
+(define-opt pause? boolean)
+(define-opt
+  pipewire-buffer
+  enumeration
+  (or (memq val '(native))
+      (and (integer? val) (>= val 1) (<= val 2000))))
+(define-opt pipewire-remote string)
+(define-opt
+  pipewire-volume-mode
+  enumeration
+  (memq val '(channel global)))
+(define-opt
+  pitch
+  double
+  (>= val 0.01)
+  (<= val 100))
+(define-opt
+  play-direction
+  enumeration
+  (memq val '(forward + backward -)))
+(define-opt
+  player-operation-mode
+  enumeration
+  (memq val '(cplayer pseudo-gui)))
+(define-opt
+  playlist-start
+  enumeration
+  (or (memq val '(auto no))
+      (and (integer? val)
+           (>= val 0)
+           (<= val 2147483647))))
+(define-opt prefetch-playlist? boolean)
+(define-opt profile list-of-string)
+(define-opt pulse-allow-suspended? boolean)
+(define-opt
+  pulse-buffer
+  enumeration
+  (or (memq val '(native))
+      (and (integer? val) (>= val 1) (<= val 2000))))
+(define-opt pulse-host string)
+(define-opt pulse-latency-hacks? boolean)
+(define-opt quiet? boolean)
+(define-opt really-quiet? boolean)
+(define-opt rebase-start-time? boolean)
+(define-opt referrer string)
+(define-opt
+  replaygain
+  enumeration
+  (memq val '(no track album)))
+(define-opt replaygain-clip? boolean)
+(define-opt
+  replaygain-fallback
+  float
+  (>= val -200)
+  (<= val 60))
+(define-opt
+  replaygain-preamp
+  float
+  (>= val -150)
+  (<= val 150))
+(define-opt reset-on-next-file list-of-string)
+(define-opt resume-playback? boolean)
+(define-opt resume-playback-check-mtime? boolean)
+(define-opt
+  rtsp-transport
+  enumeration
+  (memq val '(lavf udp tcp http udp_multicast)))
+(define-opt
+  saturation
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt save-position-on-quit? boolean)
+(define-opt
+  scale
+  enumeration
+  (memq val
+        '(bilinear
+          bicubic_fast
+          oversample
+          spline16
+          spline36
+          spline64
+          sinc
+          lanczos
+          ginseng
+          bicubic
+          hermite
+          catmull_rom
+          mitchell
+          robidoux
+          robidouxsharp
+          box
+          nearest
+          triangle
+          gaussian
+          jinc
+          ewa_lanczos
+          ewa_hanning
+          ewa_ginseng
+          ewa_lanczossharp
+          ewa_lanczos4sharpest
+          ewa_lanczossoft
+          haasnsoft
+          ewa_robidoux
+          ewa_robidouxsharp
+          bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx)))
+(define-opt
+  scale-antiring
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt scale-blur float)
+(define-opt
+  scale-clamp
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt scale-param1 float)
+(define-opt scale-param2 float)
+(define-opt
+  scale-radius
+  float
+  (>= val 0.5)
+  (<= val 16))
+(define-opt
+  scale-taper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  scale-window
+  enumeration
+  (memq val
+        '(bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx
+          jinc)))
+(define-opt scale-wparam float)
+(define-opt
+  scale-wtaper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt scaler-resizes-only? boolean)
+(define-opt
+  screen
+  enumeration
+  (or (memq val '(default))
+      (and (integer? val) (>= val 0) (<= val 32))))
+(define-opt screen-name string)
+(define-opt screenshot-avif-encoder string)
+(define-opt
+  screenshot-avif-opts
+  list-of-key-value)
+(define-opt screenshot-avif-pixfmt string)
+(define-opt screenshot-directory string)
+(define-opt
+  screenshot-format
+  enumeration
+  (memq val '(jpg jpeg png webp jxl avif)))
+(define-opt screenshot-high-bit-depth? boolean)
+(define-opt
+  screenshot-jpeg-quality
+  integer
+  (>= val 0)
+  (<= val 100))
+(define-opt
+  screenshot-jpeg-source-chroma?
+  boolean)
+(define-opt
+  screenshot-jxl-distance
+  double
+  (>= val 0)
+  (<= val 15))
+(define-opt
+  screenshot-jxl-effort
+  integer
+  (>= val 1)
+  (<= val 9))
+(define-opt
+  screenshot-png-compression
+  integer
+  (>= val 0)
+  (<= val 9))
+(define-opt
+  screenshot-png-filter
+  integer
+  (>= val 0)
+  (<= val 5))
+(define-opt screenshot-sw? boolean)
+(define-opt screenshot-tag-colorspace? boolean)
+(define-opt screenshot-template string)
+(define-opt
+  screenshot-webp-compression
+  integer
+  (>= val 0)
+  (<= val 6))
+(define-opt screenshot-webp-lossless? boolean)
+(define-opt
+  screenshot-webp-quality
+  integer
+  (>= val 0)
+  (<= val 100))
+(define-opt script-opts list-of-key-value)
+(define-opt scripts list-of-string)
+(define-opt
+  secondary-sid
+  enumeration
+  (or (memq val '(no auto))
+      (and (integer? val) (>= val 0) (<= val 8190))))
+(define-opt
+  secondary-sub-ass-override
+  enumeration
+  (memq val '(no yes scale force strip)))
+(define-opt secondary-sub-delay float)
+(define-opt
+  secondary-sub-pos
+  float
+  (>= val 0)
+  (<= val 150))
+(define-opt secondary-sub-visibility? boolean)
+(define-opt sharpen float)
+(define-opt show-in-taskbar? boolean)
+(define-opt shuffle? boolean)
+(define-opt
+  sub
+  enumeration
+  (or (memq val '(no auto))
+      (and (integer? val) (>= val 0) (<= val 8190))))
+(define-opt
+  sigmoid-center
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  sigmoid-slope
+  float
+  (>= val 1)
+  (<= val 20))
+(define-opt sigmoid-upscaling? boolean)
+(define-opt slang list-of-string)
+(define-opt snap-window? boolean)
+(define-opt
+  speed
+  double
+  (>= val 0.01)
+  (<= val 100))
+(define-opt
+  spirv-compiler
+  enumeration
+  (memq val '(auto)))
+(define-opt sstep double (>= val 0))
+(define-opt
+  start
+  relative-time-or-percent-position)
+(define-opt
+  stop-playback-on-init-failure?
+  boolean)
+(define-opt
+  stop-screensaver
+  enumeration
+  (memq val '(no yes always)))
+(define-opt
+  stream-buffer-size
+  byte-size
+  (>= val 4096)
+  (<= val 536870912))
+(define-opt stream-dump string)
+(define-opt stream-lavf-o list-of-key-value)
+(define-opt stream-record string)
+(define-opt stretch-dvd-subs? boolean)
+(define-opt
+  stretch-image-subs-to-screen?
+  boolean)
+(define-opt
+  sub-align-x
+  enumeration
+  (memq val '(left center right)))
+(define-opt
+  sub-align-y
+  enumeration
+  (memq val '(top center bottom)))
+(define-opt sub-ass? boolean)
+(define-opt sub-ass-force-margins? boolean)
+(define-opt
+  sub-ass-hinting
+  enumeration
+  (memq val '(none light normal native)))
+(define-opt sub-ass-justify? boolean)
+(define-opt
+  sub-ass-line-spacing
+  float
+  (>= val -1000)
+  (<= val 1000))
+(define-opt
+  sub-ass-override
+  enumeration
+  (memq val '(no yes scale force strip)))
+(define-opt sub-ass-scale-with-window? boolean)
+(define-opt
+  sub-ass-shaper
+  enumeration
+  (memq val '(simple complex)))
+(define-opt
+  sub-ass-style-overrides
+  list-of-string)
+(define-opt sub-ass-styles string)
+(define-opt
+  sub-ass-use-video-data
+  enumeration
+  (memq val '(none aspect-ratio all)))
+(define-opt
+  sub-ass-video-aspect-override
+  aspect
+  (>= val 0)
+  (<= val 10))
+(define-opt
+  sub-ass-vsfilter-color-compat
+  enumeration
+  (memq val '(no basic full force-601)))
+(define-opt
+  sub-auto
+  enumeration
+  (memq val '(no exact fuzzy all)))
+(define-opt sub-auto-exts list-of-string)
+(define-opt sub-back-color color)
+(define-opt
+  sub-blur
+  float
+  (>= val 0)
+  (<= val 20))
+(define-opt sub-bold? boolean)
+(define-opt
+  sub-border-style
+  enumeration
+  (memq val
+        '(outline-and-shadow opaque-box background-box)))
+(define-opt sub-clear-on-seek? boolean)
+(define-opt sub-codepage string)
+(define-opt sub-color color)
+(define-opt sub-create-cc-track? boolean)
+(define-opt sub-delay float)
+(define-opt sub-demuxer string)
+(define-opt sub-file-paths list-of-string)
+(define-opt sub-files list-of-string)
+(define-opt sub-filter-jsre list-of-string)
+(define-opt sub-filter-regex list-of-string)
+(define-opt sub-filter-regex-enable? boolean)
+(define-opt sub-filter-regex-plain? boolean)
+(define-opt sub-filter-regex-warn? boolean)
+(define-opt sub-filter-sdh? boolean)
+(define-opt sub-filter-sdh-enclosures string)
+(define-opt sub-filter-sdh-harder? boolean)
+(define-opt sub-fix-timing? boolean)
+(define-opt sub-font string)
+(define-opt
+  sub-font-provider
+  enumeration
+  (memq val '(auto none fontconfig)))
+(define-opt
+  sub-font-size
+  float
+  (>= val 1)
+  (<= val 9000))
+(define-opt sub-fonts-dir string)
+(define-opt sub-forced-events-only? boolean)
+(define-opt sub-fps float)
+(define-opt
+  sub-gauss
+  float
+  (>= val 0)
+  (<= val 3))
+(define-opt sub-gray? boolean)
+(define-opt sub-italic? boolean)
+(define-opt
+  sub-justify
+  enumeration
+  (memq val '(auto left center right)))
+(define-opt sub-lavc-o list-of-key-value)
+(define-opt
+  sub-margin-x
+  integer
+  (>= val 0)
+  (<= val 300))
+(define-opt
+  sub-margin-y
+  integer
+  (>= val 0)
+  (<= val 600))
+(define-opt sub-outline-color color)
+(define-opt sub-outline-size float)
+(define-opt sub-past-video-end? boolean)
+(define-opt
+  sub-pos
+  float
+  (>= val 0)
+  (<= val 150))
+(define-opt
+  sub-scale
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt sub-scale-by-window? boolean)
+(define-opt sub-scale-with-window? boolean)
+(define-opt sub-shadow-offset float)
+(define-opt
+  sub-spacing
+  float
+  (>= val -10)
+  (<= val 10))
+(define-opt sub-speed float)
+(define-opt sub-stretch-durations? boolean)
+(define-opt sub-use-margins? boolean)
+(define-opt sub-visibility? boolean)
+(define-opt sub-vsfilter-bidi-compat? boolean)
+(define-opt
+  subs-fallback
+  enumeration
+  (memq val '(no default yes)))
+(define-opt
+  subs-fallback-forced
+  enumeration
+  (memq val '(no yes always)))
+(define-opt subs-match-os-language? boolean)
+(define-opt
+  subs-with-matching-audio
+  enumeration
+  (memq val '(no forced yes)))
+(define-opt
+  swapchain-depth
+  integer
+  (>= val 1)
+  (<= val 8))
+(define-opt sws-allow-zimg? boolean)
+(define-opt sws-bitexact? boolean)
+(define-opt
+  sws-cgb
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt sws-chs integer)
+(define-opt
+  sws-cs
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt sws-cvs integer)
+(define-opt sws-fast? boolean)
+(define-opt
+  sws-lgb
+  float
+  (>= val 0)
+  (<= val 100))
+(define-opt
+  sws-ls
+  float
+  (>= val -100)
+  (<= val 100))
+(define-opt
+  sws-scaler
+  enumeration
+  (memq val
+        '(fast-bilinear
+          bilinear
+          bicubic
+          x
+          point
+          area
+          bicublin
+          gauss
+          sinc
+          lanczos
+          spline)))
+(define-opt target-colorspace-hint? boolean)
+(define-opt
+  target-contrast
+  enumeration
+  (or (memq val '(auto inf))
+      (and (integer? val) (>= val 10) (<= val 1000000))))
+(define-opt
+  target-gamut
+  enumeration
+  (memq val
+        '(auto bt.601-525
+               bt.601-625
+               bt.709
+               bt.2020
+               bt.470m
+               apple
+               adobe
+               prophoto
+               cie1931
+               dci-p3
+               display-p3
+               v-gamut
+               s-gamut
+               ebu3213
+               film-c
+               aces-ap0
+               aces-ap1)))
+(define-opt target-lut string)
+(define-opt
+  target-peak
+  enumeration
+  (or (memq val '(auto))
+      (and (integer? val) (>= val 10) (<= val 10000))))
+(define-opt
+  target-prim
+  enumeration
+  (memq val
+        '(auto bt.601-525
+               bt.601-625
+               bt.709
+               bt.2020
+               bt.470m
+               apple
+               adobe
+               prophoto
+               cie1931
+               dci-p3
+               display-p3
+               v-gamut
+               s-gamut
+               ebu3213
+               film-c
+               aces-ap0
+               aces-ap1)))
+(define-opt
+  target-trc
+  enumeration
+  (memq val
+        '(auto bt.1886
+               srgb
+               linear
+               gamma1.8
+               gamma2.0
+               gamma2.2
+               gamma2.4
+               gamma2.6
+               gamma2.8
+               prophoto
+               pq
+               hlg
+               v-log
+               s-log1
+               s-log2
+               st428)))
+(define-opt taskbar-progress? boolean)
+(define-opt
+  teletext-page
+  integer
+  (>= val -1)
+  (<= val 999))
+(define-opt temporal-dither? boolean)
+(define-opt
+  temporal-dither-period
+  integer
+  (>= val 1)
+  (<= val 128))
+(define-opt
+  term-osd
+  enumeration
+  (memq val '(force auto no)))
+(define-opt term-osd-bar? boolean)
+(define-opt term-osd-bar-chars string)
+(define-opt term-playing-msg string)
+(define-opt term-status-msg string)
+(define-opt term-title string)
+(define-opt terminal? boolean)
+(define-opt title string)
+(define-opt title-bar? boolean)
+(define-opt tls-ca-file string)
+(define-opt tls-cert-file string)
+(define-opt tls-key-file string)
+(define-opt tls-verify? boolean)
+(define-opt
+  tone-mapping
+  enumeration
+  (memq val
+        '(auto clip
+               mobius
+               reinhard
+               hable
+               gamma
+               linear
+               spline
+               bt.2390
+               bt.2446a
+               st2094-40
+               st2094-10)))
+(define-opt
+  tone-mapping-max-boost
+  float
+  (>= val 1)
+  (<= val 10))
+(define-opt tone-mapping-param float)
+(define-opt tone-mapping-visualize? boolean)
+(define-opt track-auto-selection? boolean)
+(define-opt
+  tscale
+  enumeration
+  (memq val
+        '(oversample
+          linear
+          spline16
+          spline36
+          spline64
+          sinc
+          lanczos
+          ginseng
+          bicubic
+          hermite
+          catmull_rom
+          mitchell
+          robidoux
+          robidouxsharp
+          box
+          nearest
+          triangle
+          gaussian
+          bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx
+          jinc)))
+(define-opt
+  tscale-antiring
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt tscale-blur float)
+(define-opt
+  tscale-clamp
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt tscale-param1 float)
+(define-opt tscale-param2 float)
+(define-opt
+  tscale-radius
+  float
+  (>= val 0.5)
+  (<= val 16))
+(define-opt
+  tscale-taper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  tscale-window
+  enumeration
+  (memq val
+        '(bartlett
+          cosine
+          hanning
+          tukey
+          hamming
+          quadric
+          welch
+          kaiser
+          blackman
+          sphinx
+          jinc)))
+(define-opt tscale-wparam float)
+(define-opt
+  tscale-wtaper
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt untimed? boolean)
+(define-opt use-embedded-icc-profile? boolean)
+(define-opt use-filedir-conf? boolean)
+(define-opt user-agent string)
+(define-opt vaapi-device string)
+(define-opt vd string)
+(define-opt vd-apply-cropping? boolean)
+(define-opt vd-lavc-assume-old-x264? boolean)
+(define-opt vd-lavc-bitexact? boolean)
+(define-opt vd-lavc-check-hw-profile? boolean)
+(define-opt
+  vd-lavc-dr
+  enumeration
+  (memq val '(auto no yes)))
+(define-opt vd-lavc-fast? boolean)
+(define-opt
+  vd-lavc-film-grain
+  enumeration
+  (memq val '(auto cpu gpu)))
+(define-opt
+  vd-lavc-framedrop
+  enumeration
+  (memq val
+        '(none default nonref bidir nonkey all)))
+(define-opt vd-lavc-o list-of-key-value)
+(define-opt vd-lavc-show-all? boolean)
+(define-opt
+  vd-lavc-skipframe
+  enumeration
+  (memq val
+        '(none default nonref bidir nonkey all)))
+(define-opt
+  vd-lavc-skipidct
+  enumeration
+  (memq val
+        '(none default nonref bidir nonkey all)))
+(define-opt
+  vd-lavc-skiploopfilter
+  enumeration
+  (memq val
+        '(none default nonref bidir nonkey all)))
+(define-opt
+  vd-lavc-software-fallback
+  enumeration
+  (or (memq val '(no yes))
+      (and (integer? val)
+           (>= val 1)
+           (<= val 2147483647))))
+(define-opt vd-lavc-threads integer (>= val 0))
+(define-opt vd-queue-enable? boolean)
+(define-opt
+  vd-queue-max-bytes
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  vd-queue-max-samples
+  integer64
+  (>= val 0))
+(define-opt vd-queue-max-secs double (>= val 0))
+(define-opt vf list-of-object-setting)
+(define-opt
+  video
+  enumeration
+  (or (memq val '(no auto))
+      (and (integer? val) (>= val 0) (<= val 8190))))
+(define-opt
+  video-align-x
+  float
+  (>= val -1)
+  (<= val 1))
+(define-opt
+  video-align-y
+  float
+  (>= val -1)
+  (<= val 1))
+(define-opt
+  video-aspect-method
+  enumeration
+  (memq val '(bitstream container)))
+(define-opt
+  video-aspect-override
+  aspect
+  (>= val -1)
+  (<= val 10))
+(define-opt
+  video-backward-batch
+  integer
+  (>= val 0)
+  (<= val 1024))
+(define-opt
+  video-backward-overlap
+  enumeration
+  (or (memq val '(auto))
+      (and (integer? val) (>= val 0) (<= val 1024))))
+(define-opt video-crop video-rectangle)
+(define-opt video-exts list-of-string)
+(define-opt video-latency-hacks? boolean)
+(define-opt
+  video-margin-ratio-bottom
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  video-margin-ratio-left
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  video-margin-ratio-right
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  video-margin-ratio-top
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt video-osd? boolean)
+(define-opt
+  video-output-levels
+  enumeration
+  (memq val '(auto limited full)))
+(define-opt video-pan-x float)
+(define-opt video-pan-y float)
+(define-opt
+  video-reversal-buffer
+  byte-size
+  (>= val 0)
+  (<= val 4.6116860184274e18))
+(define-opt
+  video-rotate
+  enumeration
+  (or (memq val '(no))
+      (and (integer? val) (>= val 0) (<= val 359))))
+(define-opt
+  video-scale-x
+  float
+  (>= val 0)
+  (<= val 10000))
+(define-opt
+  video-scale-y
+  float
+  (>= val 0)
+  (<= val 10000))
+(define-opt
+  video-sync
+  enumeration
+  (memq val
+        '(audio display-resample
+                display-resample-vdrop
+                display-resample-desync
+                display-tempo
+                display-adrop
+                display-vdrop
+                display-desync
+                desync)))
+(define-opt
+  video-sync-max-audio-change
+  double
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  video-sync-max-factor
+  integer
+  (>= val 1)
+  (<= val 10))
+(define-opt
+  video-sync-max-video-change
+  double
+  (>= val 0))
+(define-opt
+  video-timing-offset
+  double
+  (>= val 0)
+  (<= val 1))
+(define-opt
+  video-unscaled
+  enumeration
+  (memq val '(no yes downscale-big)))
+(define-opt
+  video-zoom
+  float
+  (>= val -20)
+  (<= val 20))
+(define-opt vlang list-of-string)
+(define-opt vo list-of-object-setting)
+(define-opt vo-image-avif-encoder string)
+(define-opt vo-image-avif-opts list-of-key-value)
+(define-opt vo-image-avif-pixfmt string)
+(define-opt
+  vo-image-format
+  enumeration
+  (memq val '(jpg jpeg png webp jxl avif)))
+(define-opt vo-image-high-bit-depth? boolean)
+(define-opt
+  vo-image-jpeg-quality
+  integer
+  (>= val 0)
+  (<= val 100))
+(define-opt vo-image-jpeg-source-chroma? boolean)
+(define-opt
+  vo-image-jxl-distance
+  double
+  (>= val 0)
+  (<= val 15))
+(define-opt
+  vo-image-jxl-effort
+  integer
+  (>= val 1)
+  (<= val 9))
+(define-opt vo-image-outdir string)
+(define-opt
+  vo-image-png-compression
+  integer
+  (>= val 0)
+  (<= val 9))
+(define-opt
+  vo-image-png-filter
+  integer
+  (>= val 0)
+  (<= val 5))
+(define-opt vo-image-tag-colorspace? boolean)
+(define-opt
+  vo-image-webp-compression
+  integer
+  (>= val 0)
+  (<= val 6))
+(define-opt vo-image-webp-lossless? boolean)
+(define-opt
+  vo-image-webp-quality
+  integer
+  (>= val 0)
+  (<= val 100))
+(define-opt vo-kitty-alt-screen? boolean)
+(define-opt vo-kitty-cols integer)
+(define-opt vo-kitty-config-clear? boolean)
+(define-opt vo-kitty-height integer)
+(define-opt vo-kitty-left integer)
+(define-opt vo-kitty-rows integer)
+(define-opt vo-kitty-top integer)
+(define-opt vo-kitty-use-shm? boolean)
+(define-opt vo-kitty-width integer)
+(define-opt
+  vo-null-fps
+  double
+  (>= val 0)
+  (<= val 10000))
+(define-opt vo-sixel-alt-screen? boolean)
+(define-opt vo-sixel-buffered? boolean)
+(define-opt vo-sixel-cols integer)
+(define-opt vo-sixel-config-clear? boolean)
+(define-opt
+  vo-sixel-dither
+  enumeration
+  (memq val
+        '(auto none
+               atkinson
+               fs
+               jajuni
+               stucki
+               burkes
+               arithmetic
+               xor)))
+(define-opt vo-sixel-fixedpalette? boolean)
+(define-opt vo-sixel-height integer)
+(define-opt vo-sixel-left integer)
+(define-opt vo-sixel-pad-x integer)
+(define-opt vo-sixel-pad-y integer)
+(define-opt vo-sixel-reqcolors integer)
+(define-opt vo-sixel-rows integer)
+(define-opt vo-sixel-threshold integer)
+(define-opt vo-sixel-top integer)
+(define-opt vo-sixel-width integer)
+(define-opt vo-tct-256? boolean)
+(define-opt
+  vo-tct-algo
+  enumeration
+  (memq val '(plain half-blocks)))
+(define-opt
+  vo-tct-buffering
+  enumeration
+  (memq val '(pixel line frame)))
+(define-opt vo-tct-height integer)
+(define-opt vo-tct-width integer)
+(define-opt vo-vaapi-scaled-osd? boolean)
+(define-opt
+  vo-vaapi-scaling
+  enumeration
+  (memq val '(default fast hq nla)))
+(define-opt vo-vdpau-chroma-deint? boolean)
+(define-opt vo-vdpau-colorkey color)
+(define-opt vo-vdpau-composite-detect? boolean)
+(define-opt
+  vo-vdpau-denoise
+  float
+  (>= val 0)
+  (<= val 1))
+(define-opt vo-vdpau-force-yuv? boolean)
+(define-opt vo-vdpau-fps double)
+(define-opt
+  vo-vdpau-hqscaling
+  integer
+  (>= val 0)
+  (<= val 9))
+(define-opt
+  vo-vdpau-output-surfaces
+  integer
+  (>= val 2)
+  (<= val 15))
+(define-opt vo-vdpau-pullup? boolean)
+(define-opt vo-vdpau-queuetime-fs integer)
+(define-opt vo-vdpau-queuetime-windowed integer)
+(define-opt
+  vo-vdpau-sharpen
+  float
+  (>= val -1)
+  (<= val 1))
+(define-opt
+  volume
+  float
+  (>= val -1)
+  (<= val 1000))
+(define-opt
+  volume-gain
+  float
+  (>= val -150)
+  (<= val 150))
+(define-opt
+  volume-gain-max
+  float
+  (>= val 0)
+  (<= val 150))
+(define-opt
+  volume-gain-min
+  float
+  (>= val -150)
+  (<= val 0))
+(define-opt
+  volume-max
+  float
+  (>= val 100)
+  (<= val 1000))
+(define-opt vulkan-async-compute? boolean)
+(define-opt vulkan-async-transfer? boolean)
+(define-opt vulkan-device string)
+(define-opt vulkan-display-display integer)
+(define-opt vulkan-display-mode integer)
+(define-opt vulkan-display-plane integer)
+(define-opt
+  vulkan-queue-count
+  integer
+  (>= val 1)
+  (<= val 8))
+(define-opt
+  vulkan-swap-mode
+  enumeration
+  (memq val
+        '(auto fifo fifo-relaxed mailbox immediate)))
+(define-opt watch-later-directory string)
+(define-opt watch-later-options list-of-string)
+(define-opt wayland-app-id string)
+(define-opt
+  wayland-configure-bounds
+  enumeration
+  (memq val '(auto no yes)))
+(define-opt
+  wayland-content-type
+  enumeration
+  (memq val '(auto none photo video game)))
+(define-opt wayland-disable-vsync? boolean)
+(define-opt
+  wayland-edge-pixels-pointer
+  integer
+  (>= val 0)
+  (<= val 2147483647))
+(define-opt
+  wayland-edge-pixels-touch
+  integer
+  (>= val 0)
+  (<= val 2147483647))
+(define-opt wayland-present? boolean)
+(define-opt wid integer64)
+(define-opt window-dragging? boolean)
+(define-opt window-maximized? boolean)
+(define-opt window-minimized? boolean)
+(define-opt
+  window-scale
+  double
+  (>= val 0.001)
+  (<= val 100))
+(define-opt
+  write-filename-in-watch-later-config?
+  boolean)
+(define-opt
+  x11-bypass-compositor
+  enumeration
+  (memq val '(no yes fs-only never)))
+(define-opt x11-name string)
+(define-opt
+  x11-netwm
+  enumeration
+  (memq val '(auto no yes)))
+(define-opt
+  x11-present
+  enumeration
+  (memq val '(no auto yes)))
+(define-opt x11-wid-title? boolean)
+(define-opt xv-adaptor integer (>= val -1))
+(define-opt
+  xv-buffers
+  integer
+  (>= val 1)
+  (<= val 10))
+(define-opt
+  xv-ck
+  enumeration
+  (memq val '(use set cur)))
+(define-opt
+  xv-ck-method
+  enumeration
+  (memq val '(none bg man auto)))
+(define-opt xv-colorkey integer)
+(define-opt xv-port integer (>= val 0))
+(define-opt ytdl? boolean)
+(define-opt ytdl-format string)
+(define-opt ytdl-raw-options list-of-key-value)
+(define-opt
+  zimg-dither
+  enumeration
+  (memq val '(no ordered random error-diffusion)))
+(define-opt zimg-fast? boolean)
+(define-opt
+  zimg-scaler
+  enumeration
+  (memq val
+        '(point bilinear
+                bicubic
+                spline16
+                spline36
+                lanczos)))
+(define-opt
+  zimg-scaler-chroma
+  enumeration
+  (memq val
+        '(point bilinear
+                bicubic
+                spline16
+                spline36
+                lanczos)))
+(define-opt zimg-scaler-chroma-param-a double)
+(define-opt zimg-scaler-chroma-param-b double)
+(define-opt zimg-scaler-param-a double)
+(define-opt zimg-scaler-param-b double)
+(define-opt
+  zimg-threads
+  enumeration
+  (or (memq val '(auto))
+      (and (integer? val) (>= val 1) (<= val 64))))
+;;; Generated code - END.
+
+(define-record-type <mpv-profile-configuration>
+  (%make-mpv-profile-configuration data)
+  mpv-profile-configuration?
+  (data %mpv-profile-configuration-data))
+
+(define (make-mpv-profile-configuration . args)
+  ;; I am not sure how can I copy a hash-map.  Documentation does not mention
+  ;; anything.
+  (let ((new (make-hash-table)))
+    (let loop ((args args))
+      (match args
+        ((#:inherit cfg . tail)
+         (hash-for-each (lambda (key val)
+                          (hashq-set! new key val))
+                        (%mpv-profile-configuration-data cfg))
+         (loop tail))
+        (((? keyword? key) val . tail)
+         (let* ((key (keyword->symbol key))
+                (opt (hashq-ref %opts key)))
+           (unless opt
+             (raise-exception
+              (formatted-message
+               (G_ "option ~a not found for mpv-profile-configuration") key)))
+           (if (maybe-value-set? val)
+               (if ((profile-option-type-check opt) val)
+                   (hashq-set! new key (cons val
+                                             (profile-option-serializer opt)))
+                   (raise-exception
+                    (formatted-message
+                     (G_ "invalid mpv configuration for ~a: ~a~%")
+                     key val)))
+               (hashq-remove! new key)))
+         (loop tail))
+        (()
+         (%make-mpv-profile-configuration new))))))
+
+(define (serialize-mpv-profile-configuration _ cfg)
+  (let ((sorted (sort
+                 (hash-map->list cons (%mpv-profile-configuration-data cfg))
+                 (lambda (a b)
+                   (string<? (symbol->string (car a))
+                             (symbol->string (car b)))))))
+    #~(string-append
+       #$@(map (match-lambda
+                 ((field-name . value)
+                  ((cdr value) field-name (car value))))
+               sorted))))
+
+
+
+
+;;;
+;;; Configuration base.
+;;;
+(define (serialize-mpv/mpv-profile-configurations _ profiles)
+  #~(string-append
+     #$@(map (match-lambda
+               ((name . config)
+                #~(string-append
+                   #$(format #f "[~a]~%" name)
+                   #$(serialize-mpv-profile-configuration _ config))))
+             profiles)))
+(define (mpv/mpv-profile-configurations? alist)
+  (and (list? alist)
+       (every (match-lambda
+                (((? symbol?) . (? mpv-profile-configuration?)) #t)
+                (_ #f))
+              alist)))
+
+(define (serialize-mpv/extra _ value)
+  (if value
+      #~(string-append #$value
+                       ;; Ensure the extra content ends in a new line.
+                       #$(if (string-suffix? "\n" value)
+                             "" "\n"))
+      #~""))
+(define (mpv/extra? val)
+  (or (string? val)
+      (gexp? val)))
+
+(define-record-type <home-mpv-configuration>
+  (%make-home-mpv-configuration global profiles extra-config)
+  home-mpv-configuration?
+  (global       home-mpv-configuration-global)
+  (profiles     home-mpv-configuration-profiles)
+  (extra-config home-mpv-configuration-extra-config))
+
+(define* (make-home-mpv-configuration
+          #:key
+          (inherit #f)
+          (global (if inherit
+                      (home-mpv-configuration-global inherit)
+                      (make-mpv-profile-configuration)))
+          (profiles (if inherit
+                        (home-mpv-configuration-profiles inherit)
+                        '()))
+          (extra-config (if inherit
+                            (home-mpv-configuration-extra-config inherit)
+                            #f)))
+  (unless (mpv-profile-configuration? global)
+    (raise-exception
+     (formatted-message
+      (G_ "global must satisfy mpv-profile-configuration?"))))
+  (unless (mpv/mpv-profile-configurations? profiles)
+    (raise-exception
+     (formatted-message
+      (G_ "profiles must be an alist of mpv-profile-configuration?"))))
+  (unless (or (not extra-config) (mpv/extra? extra-config))
+    (raise-exception
+     (formatted-message
+      (G_ "extra-config must be a string or a gexp"))))
+  (%make-home-mpv-configuration global profiles extra-config))
+
+(define (serialize-home-mpv-configuration cfg)
+  #~(string-append #$(serialize-mpv-profile-configuration
+                      'global
+                      (home-mpv-configuration-global cfg))
+                   #$(serialize-mpv/mpv-profile-configurations
+                      'profiles
+                      (home-mpv-configuration-profiles cfg))
+                   #$(serialize-mpv/extra
+                      'extra-config
+                      (home-mpv-configuration-extra-config cfg))))
+
+(define (mpv-configuration-files cfg)
+  `(("mpv/mpv.conf" ,(mixed-text-file "mpv.conf"
+                                      (serialize-home-mpv-configuration cfg)))))
+
+(define home-mpv-service-type
+  (service-type
+   (name 'home-mpv)
+   (extensions
+    (list (service-extension home-xdg-configuration-files-service-type
+                             mpv-configuration-files)))
+   (description
+    "Install configuration files for mpv into XDG configuration directory.")))
diff --git a/gnu/local.mk b/gnu/local.mk
index e6ece8cc48..d132e79ad2 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -113,6 +113,7 @@  GNU_SYSTEM_MODULES =				\
   %D%/home/services/mail.scm			\
   %D%/home/services/media.scm			\
   %D%/home/services/messaging.scm		\
+  %D%/home/services/mpv.scm     		\
   %D%/home/services/music.scm			\
   %D%/home/services/pm.scm			\
   %D%/home/services/shells.scm			\