# MPV - mpv.conf # classicjazz - 2026-03-07 # Details about configuring MPV for high quality video are covered here: https://freetime.mikeconnelly.com/archives/5371 # The latest version of this file is located here: https://github.com/classicjazz/mpv-config # All MPV options are covered here: https://github.com/mpv-player/mpv/blob/master/DOCS/man/options.rst # This configuration file uses vo=gpu-next (libplacebo-based renderer) # https://github.com/mpv-player/mpv/wiki/GPU-Next-vs-GPU # On macOS, gpu-api=vulkan via MoltenVK is required. There is no native Metal backend # in libplacebo; OpenGL is deprecated on macOS. MoltenVK translates Vulkan to Metal. # Tested on a Mac Studio (M1 Max) and MacBook Air (M4) with mpv v0.41.1, # libplacebo v7.360.0, FFmpeg 8.0.1, and MoltenVK v1.4.1 on MacOS Tahoe 26.3. # Conditional Profiles are used throughout (auto-profiles.lua is no longer required). ############################################################################## # SELF-SERVICE CONFIGURATION # # These are the settings most likely to need adjustment for your setup. # # Everything else is generally safe to leave at defaults. # ############################################################################## # --- GPU API --- # macOS (MoltenVK/Vulkan): gpu-api=vulkan [required for vo=gpu-next on macOS] # Linux/Windows (Vulkan): gpu-api=vulkan # Windows (DirectX): gpu-api=d3d11 # Fallback (any platform): gpu-api=opengl [lower quality, use only if Vulkan unavailable] gpu-api=vulkan # --- Display Geometry --- # Controls the mpv window size at launch. # Use autofit=100% to match whatever display mpv opens on (recommended for # multi-display setups or non-4K displays such as the MacBook Air 2560x1664). # Uncomment geometry= instead if you always use a fixed display and want mpv # to render at exactly that resolution rather than relying on macOS scaling. autofit=100% # geometry=3840x2160 # force 4K output; use on a dedicated 4K display/TV # --- HiDPI Scaling --- # no-hidpi-window-scale prevents macOS from scaling the mpv window, # ensuring mpv renders at the display's full pixel resolution rather than # the lower logical resolution macOS uses by default (e.g. 1470x956 on the # MacBook Air instead of 2560x1664). Remove or comment out on non-macOS. no-hidpi-window-scale # --- Display Refresh Rate --- # Must match your display's actual refresh rate for motion interpolation to work. # 60 = 4K TV or standard monitor # 120 or 240 = high refresh rate display # To check: macOS System Settings > Displays, or run `mpv --display-fps-override=0` # and read the detected rate from the terminal output. display-fps-override=60 # --- Subtitle Font --- # SFProRounded-Medium is available on macOS. Replace with a font available # on your system, or remove to use mpv's built-in default (Cantarell). sub-font="SFProRounded-Medium" # --- Shader Performance Tier --- # The profiles below use ArtCNN_C4F16 (luma doubling) and ravu-zoom-ar-r3 # (fractional upscaling) by default. If your GPU struggles, switch the active # glsl-shader lines in each profile to the commented ravu-lite-ar-r4 fallback. # See the Upscaling Logic section below for the reasoning behind shader choice. ############################################################################## ########### # General # ########### vo=gpu-next hwdec=auto # enable best HW decoder; turn off for software decoding vulkan-async-compute=yes vulkan-async-transfer=yes vulkan-queue-count=1 vd-lavc-dr=yes reset-on-next-file=audio-delay,mute,pause,speed,sub-delay,video-aspect-override,video-pan-x,video-pan-y,video-rotate,video-zoom,volume framedrop=no ###### # UI # ###### border=no # hide the window title bar msg-color=yes # color log messages on terminal term-osd-bar=yes # display a progress bar on the terminal force-window=immediate cursor-autohide=1000 # autohide the cursor after 1s # fullscreen=yes # start in fullscreen mode by default macos-title-bar-appearance=vibrantDark macos-title-bar-material=popover macos-fs-animation-duration=0 sub-font-size=32 sub-border-size=1 ############ # Playback # ############ deinterlace=no # global reset of deinterlacing to off keep-open=yes # keep the player open after the file ends rather than closing the window save-position-on-quit=yes # resume playback from last position on reopen (writes to ~/.config/mpv/watch_later/) ############## # Colorspace # ############## target-prim=auto # target-prim=bt.709 # target Rec.709 for SDR TVs # target-prim=bt.2020 # target Rec.2020 (wide color gamut) for HDR TVs target-trc=auto vf=format=colorlevels=full:colormatrix=auto video-output-levels=full # --- HDR Passthrough (optional, disabled by default) --- # Uncomment target-colorspace-hint if your display supports HDR passthrough # (e.g. an HDR-capable 4K TV). This signals the display's native colorspace # to the OS/compositor, enabling the display to handle HDR tone mapping itself # rather than mpv doing it in software. Harmless on SDR displays but has no # effect either. On macOS with a non-HDR display (Mac Studio, MacBook Air), # leave this commented out. # target-colorspace-hint=yes # Uncomment hdr-compute-peak to enable real-time per-scene HDR peak brightness # measurement rather than relying solely on static stream metadata. Improves # tone-mapping accuracy on HDR content at a small GPU cost. # hdr-compute-peak=yes # --- ICC Color Profile (optional, disabled by default) --- # Uncomment icc-profile-auto to have mpv use the ICC profile currently set as # the system default for the active display. On macOS this uses the factory- # calibrated Display P3 profile for the built-in screen, giving mpv accurate # color management against the actual display primaries rather than relying on # target-prim=auto. # WARNING: Known to cause very dark output in certain scenes on some macOS # configurations (especially with vo=gpu-next). Test carefully before enabling. # If colors look wrong or scenes appear unexpectedly dark, remove this line. # icc-profile-auto=yes ########## # Dither # ########## dither-depth=auto temporal-dither=yes dither=fruit ############# # Debanding # ############# # Debanding reduces banding artifacts from low-quality or compressed sources. # iterations: number of passes (1-4). Higher = stronger but more GPU cost. # 2 is a good balance; 4 is maximum with diminishing returns above 2. # threshold: filter strength (0-4096). Higher removes more banding but risks # blurring fine detail. 35 is a reasonable default. # range: how far the filter samples (1-64). 16 is standard. # grain: adds dynamic noise to mask residual banding (0 = off). # Set to 0 if using a static grain shader instead. deband=yes deband-iterations=2 deband-threshold=35 deband-range=16 deband-grain=4 ######################### # Motion Interpolation # ######################### video-sync=display-resample interpolation=yes tscale=oversample # smoothmotion; lowest-artifact interpolation method ################ # Anti-Ringing # ################ scale-antiring=0.6 # luma upscale deringing via libplacebo # Note: dscale-antiring and cscale-antiring currently have no effect with vo=gpu-next ############################################################################### # Upscaling & Downscaling — Fallback Scalers # # # # scale= and dscale= are active in vo=gpu-next/libplacebo and serve as # # fallbacks when no GLSL shader handles the scaling step, including: # # - Content that doesn't match any profile (unusual resolutions) # # - Non-4K displays where ArtCNN's 1.3x activation threshold isn't reached # # - The final RGB output pass after shaders have run # # # # scale=ewa_lanczos — high quality polar (Jinc) luma upscale fallback # # dscale=catmull_rom — good quality luma downscale (used when mpv # # window is smaller than source, e.g. 4K on 1080p) # # # # correct-downscaling=yes — uses a properly windowed filter when downscaling # # by large ratios; included in mpv's gpu-hq profile # # linear-downscaling=yes — performs downscaling in linear light rather than # # gamma-compressed space; more correct for # # luminance blending. NOTE: if you ever add an # # SSimDownscaler shader, set this to =no instead, # # as that shader requires gamma-space input. # # correct-downscaling + linear-downscaling + # # dscale=catmull_rom are a recommended package. # # # # sigmoid-upscaling=yes — applies a sigmoid curve during upscaling to # # reduce ringing artifacts by scaling in a # # perceptually linearized space. Defaults to yes # # in libplacebo; explicit here to document intent # # and protect against future default changes. # # NOTE: has no effect when a GLSL luma shader # # (ArtCNN, ravu-zoom) is active, as those bypass # # the main scalar path. Applies to the # # scale=ewa_lanczos fallback path only. # ############################################################################### scale=ewa_lanczos dscale=catmull_rom correct-downscaling=yes linear-downscaling=yes sigmoid-upscaling=yes ############################################################################### # Upscaling Logic — Per-Resolution Profiles # # # # Goal: highest quality upscale to the output display in the fewest passes, # # preferring a single upscale where possible. # # # # Two shader strategies are used: # # # # 1. ArtCNN_C4F16 — fixed 2x luma doubler (CNN-based, real-time) # # - Use when source is exactly half the display height # # - e.g. 1080p → 4K (1080 * 2 = 2160): single clean 2x pass # # - Shader activates only when scale factor > 1.3 (hardcoded in shader) # # - On a non-4K display (e.g. MacBook Air 2560x1664), 1080p is only a # # ~1.33x scale so ArtCNN barely activates; scale=ewa_lanczos takes over # # - ravu-lite-ar-r4 is a lighter-weight 2x doubler alternative # # # # 2. ravu-zoom-ar-r3 — arbitrary-ratio luma upscaler (fractional, one pass) # # - Use when source height * 2 ≠ display height (non-2x scale factor) # # - e.g. 720p → 4K (720 * 2 = 1440, not 2160): ravu-zoom scales # # directly from 720p to 4K in a single pass, avoiding a 2-step chain # # (720p → 1440p via ArtCNN, then 1440p → 4K via scale=) # # - Also used for SD: 480p/576p → 4K is a 4-9x scale, handled directly # # # # Chroma: all YUV 4:2:0 content needs chroma upscaling regardless of luma. # # CfL_Prediction infers chroma from luma correlation — the best available # # real-time chroma upscaler. CfL_Prediction_Lite is a lighter alternative. # # # # MPV shader processing order: # # 1. Luma shaders (ArtCNN or ravu-zoom) # # 2. Chroma shaders (CfL_Prediction) # # 3. Chroma scaled to luma size # # 4. Both converted to RGB # # 5. Main scaler (scale=) applied for final output resolution # # # # References: # # Shader stage diagram: https://github.com/mpv-player/mpv/wiki/Video-output---shader-stage-diagram # Upscaler analysis: https://artoriuz.github.io/blog/mpv_upscaling.html # ############################################################################### ############ # Profiles # ############ [4k60] # 2160p @ 60fps (3840x2160 UHDTV) profile-desc=4k60 profile-cond=((width ==3840 and height ==2160) and p["estimated-vf-fps"]>=31) # no deinterlacer required: presume progressive interpolation=no # no motion interpolation needed at 60fps deband=no # UHD content is typically wide color gamut; debanding risks clipping fine gradients # no luma upscaling needed: source is already 4K glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # UHD is YUV420: chroma upscaling still needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [4k30] # 2160p @ 24-30fps (3840x2160 UHDTV — common for camera footage, streaming) profile-desc=4k30 profile-cond=((width ==3840 and height ==2160) and p["estimated-vf-fps"]<31) # no deinterlacer required: presume progressive # motion interpolation applies (inherited from global interpolation=yes) deband=no # UHD content is typically wide color gamut; debanding risks clipping fine gradients # no luma upscaling needed: source is already 4K glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # UHD is YUV420: chroma upscaling still needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [full-hd60] # 1080p @ 60fps (progressive ATSC) profile-desc=full-hd60 profile-cond=((width ==1920 and height ==1080) and not p["video-frame-info/interlaced"] and p["estimated-vf-fps"]>=31) # no deinterlacer required: presume progressive interpolation=no # no motion interpolation needed at 60fps # debanding applies (inherited from global deband=yes) # luma: 1080 * 2 = 2160 → exact 2x scale to 4K; ArtCNN_C4F16 handles in one pass glsl-shader="~/.config/mpv/shaders/ArtCNN_C4F16.glsl" # luma upscaling (2x doubler) # glsl-shader="~/.config/mpv/shaders/ravu-lite-ar-r4.hook" # lighter 2x doubler alternative glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # HD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [full-hd30] # 1080p @ 24-30fps (NextGen TV/ATSC 3.0, progressive Blu-ray) profile-desc=full-hd30 profile-cond=((width ==1920 and height ==1080) and not p["video-frame-info/interlaced"] and p["estimated-vf-fps"]<31) # no deinterlacer required: presume progressive # motion interpolation applies (inherited from global interpolation=yes) # debanding applies (inherited from global deband=yes) # luma: 1080 * 2 = 2160 → exact 2x scale to 4K; ArtCNN_C4F16 handles in one pass glsl-shader="~/.config/mpv/shaders/ArtCNN_C4F16.glsl" # luma upscaling (2x doubler) # glsl-shader="~/.config/mpv/shaders/ravu-lite-ar-r4.hook" # lighter 2x doubler alternative glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # HD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [full-hd-interlaced] # 1080i @ 24-30fps (HDTV, interlaced Blu-rays) profile-desc=full-hd-interlaced profile-cond=((width ==1920 and height ==1080) and p["video-frame-info/interlaced"] and p["estimated-vf-fps"]<31) deinterlace=yes # MPV uses BWDIF (motion-adaptive) by default # motion interpolation applies (inherited from global interpolation=yes) # debanding applies (inherited from global deband=yes) # luma: 1080 * 2 = 2160 → exact 2x scale to 4K; ArtCNN_C4F16 handles in one pass glsl-shader="~/.config/mpv/shaders/ArtCNN_C4F16.glsl" # luma upscaling (2x doubler) # glsl-shader="~/.config/mpv/shaders/ravu-lite-ar-r4.hook" # lighter 2x doubler alternative glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # HD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [hd] # 720p @ 60fps (HDTV, Blu-ray — progressive) profile-desc=hd profile-cond=(width ==1280 and height ==720) # no deinterlacer required: presume progressive interpolation=no # no motion interpolation needed at 60fps # debanding applies (inherited from global deband=yes) # luma: 720 * 2 = 1440 ≠ 2160 → not a clean 2x to 4K; ravu-zoom scales directly # in one pass from 720p to output resolution (avoids 720p→1440p→4K two-step chain) glsl-shader="~/.config/mpv/shaders/ravu-zoom-ar-r3.hook" # luma upscaling (arbitrary ratio, single pass) glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # HD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [sdtv-ntsc] # 640x480, 704x480, 720x480 @ 30fps (NTSC DVD — interlaced) profile-desc=sdtv-ntsc profile-cond=((width ==640 and height ==480) or (width ==704 and height ==480) or (width ==720 and height ==480)) deinterlace=yes # MPV uses BWDIF by default # motion interpolation applies (inherited from global interpolation=yes) # debanding applies (inherited from global deband=yes) # luma: 480 * 2 = 960 ≠ 2160 → not a clean 2x; ravu-zoom scales directly in one pass glsl-shader="~/.config/mpv/shaders/ravu-zoom-ar-r3.hook" # luma upscaling (arbitrary ratio, single pass) glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # SD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling [sdtv-pal] # 352x576, 480x576, 544x576, 720x576 @ 30fps (PAL broadcast or DVD — interlaced) profile-desc=sdtv-pal profile-cond=((width ==352 and height ==576) or (width ==480 and height ==576) or (width ==544 and height ==576) or (width ==720 and height ==576)) deinterlace=yes # MPV uses BWDIF by default # motion interpolation applies (inherited from global interpolation=yes) # debanding applies (inherited from global deband=yes) # luma: 576 * 2 = 1152 ≠ 2160 → not a clean 2x; ravu-zoom scales directly in one pass glsl-shader="~/.config/mpv/shaders/ravu-zoom-ar-r3.hook" # luma upscaling (arbitrary ratio, single pass) glsl-shader="~/.config/mpv/shaders/CfL_Prediction.glsl" # SD is YUV420: chroma upscaling needed # glsl-shader="~/.config/mpv/shaders/CfL_Prediction_Lite.glsl" # lighter chroma upscaling ################################### # Protocol Specific Configuration # ################################### [protocol.http] hls-bitrate=max # use max quality for HLS streams cache=yes no-cache-pause # don't pause when the cache runs low [protocol.https] profile=protocol.http [protocol.ytdl] profile=protocol.http