Skip to content

Instantly share code, notes, and snippets.

@anthonybaldwin
Forked from natyusha/autovsr.lua
Last active March 10, 2026 21:31
Show Gist options
  • Select an option

  • Save anthonybaldwin/1e49b28b49babf64f159cb793c506333 to your computer and use it in GitHub Desktop.

Select an option

Save anthonybaldwin/1e49b28b49babf64f159cb793c506333 to your computer and use it in GitHub Desktop.
AutoVSR + RTX HDR for MPV

AutoVSR + RTX HDR for MPV

This Lua script automatically enables NVIDIA RTX Video Super Resolution (VSR) and RTX HDR in MPV

Edited original via Claude

Features:

  • RTX VSR: AI-enhanced video upscaling based on display and video resolution
  • RTX HDR: Converts SDR content to HDR when Windows HDR is enabled
  • Applies nv12 pixel format to 10-bit HEVC (required for VSR compatibility)
  • Both features work independently or together

Requirements:

  • NVIDIA RTX GPU (20 series or newer)
  • Windows HDR enabled (for RTX HDR feature)
  • MPV with: --vo=gpu --gpu-api=d3d11 --hwdec=d3d11va

Usage:

  1. Enable in NVIDIA App under "RTX Video Enhancements":
    • "Super Resolution"
    • "RTX Video Enhancement" (for HDR)
  2. Place script in your MPV scripts folder
  3. Restart MPV

Keyboard Shortcuts:

  • Ctrl+Shift+R - Toggle RTX VSR (default: on)
  • Ctrl+Shift+H - Toggle RTX HDR (default: on)
  • Ctrl+Shift+S - Show detailed status

🔗 Original discussions:

local mp = require 'mp'
-- Configuration
local autovsr_enabled = true -- Default to VSR enabled
local autohdr_enabled = true -- Default to RTX HDR (SDR to HDR) enabled
-- Function to apply VSR and RTX HDR
local function apply_filters()
-- Get video and display properties
local video_width = mp.get_property_number("width")
local video_height = mp.get_property_number("height")
local display_width = mp.get_property_number("display-width")
local display_height = mp.get_property_number("display-height")
local codec = mp.get_property("video-codec", "")
local pixelformat = mp.get_property("video-params/pixelformat", "")
local primaries = mp.get_property("video-params/primaries", "")
local gamma = mp.get_property("video-params/gamma", "")
-- Validate properties
if not (video_width and video_height and display_width and display_height and codec and pixelformat) then
mp.osd_message("RTX: Missing video properties, retrying...", 1)
return
end
-- Calculate scale factor and round to nearest 0.1
local scale = math.max(display_width / video_width, display_height / video_height)
scale = math.floor(scale * 10) / 10
-- Remove existing filters
mp.commandv("vf", "remove", "@format-nv12")
mp.commandv("vf", "remove", "@rtx-vsr")
mp.commandv("vf", "remove", "@rtx-hdr")
mp.commandv("vf", "remove", "@rtx-combined")
-- Detect if content is SDR (not HDR)
local is_sdr = true
if primaries == "bt.2020" or gamma == "pq" or gamma == "hlg" then
is_sdr = false
end
-- Apply format conversion for Main 10 HEVC if needed
if codec:lower():match("hevc") or codec:lower():match("h%.265") then
if pixelformat:match("p10le$") or pixelformat == "p010" then
mp.commandv("vf", "append", "@format-nv12:format=nv12")
end
end
local status_msg = ""
-- Set output colorspace for HDR when enabled
if is_sdr and autohdr_enabled then
mp.set_property("d3d11-output-csp", "srgb")
end
-- Apply filters based on what's enabled
if (scale > 1 and autovsr_enabled) and (is_sdr and autohdr_enabled) then
-- Both VSR and HDR - combine in single filter
mp.commandv("vf", "append", "@rtx-combined:d3d11vpp=scaling-mode=nvidia:scale=" .. scale .. ":format=nv12:nvidia-true-hdr")
status_msg = "VSR (" .. scale .. "x) + RTX HDR"
elseif scale > 1 and autovsr_enabled then
-- VSR only
mp.commandv("vf", "append", "@rtx-vsr:d3d11vpp=scaling-mode=nvidia:scale=" .. scale)
status_msg = "VSR (" .. scale .. "x)"
elseif is_sdr and autohdr_enabled then
-- RTX HDR only - using the syntax from the comment
mp.commandv("vf", "append", "@rtx-hdr:d3d11vpp=format=nv12:nvidia-true-hdr")
status_msg = "RTX HDR"
end
-- Show status if any filter was applied
if status_msg ~= "" then
mp.osd_message(status_msg .. " ON", 2)
end
end
-- Function to toggle VSR
local function toggle_vsr()
autovsr_enabled = not autovsr_enabled
apply_filters()
mp.osd_message("RTX VSR " .. (autovsr_enabled and "ON" or "OFF"), 2)
end
-- Function to toggle RTX HDR (SDR to HDR)
local function toggle_hdr()
autohdr_enabled = not autohdr_enabled
-- Reset d3d11-output-csp when HDR is disabled
if not autohdr_enabled then
mp.set_property("d3d11-output-csp", "auto")
end
apply_filters()
mp.osd_message("RTX HDR (SDR→HDR) " .. (autohdr_enabled and "ON" or "OFF"), 2)
end
-- Function to show current status
local function show_status()
local vsr_status = autovsr_enabled and "ON" or "OFF"
local hdr_status = autohdr_enabled and "ON" or "OFF"
local vf_chain = mp.get_property("vf", "")
local output_csp = mp.get_property("d3d11-output-csp", "")
local vo = mp.get_property("vo", "")
local gpu_api = mp.get_property("gpu-api", "")
local hwdec = mp.get_property("hwdec-current", "")
local active_filters = ""
if vf_chain:find("scaling%-mode=nvidia") then
active_filters = active_filters .. "VSR "
end
if vf_chain:find("nvidia%-true%-hdr") then
active_filters = active_filters .. "RTX-HDR "
end
if active_filters == "" then
active_filters = "None"
end
-- Check if content is HDR
local primaries = mp.get_property("video-params/primaries", "")
local gamma = mp.get_property("video-params/gamma", "")
local content_type = "SDR"
if primaries == "bt.2020" or gamma == "pq" or gamma == "hlg" then
content_type = "HDR (native)"
end
-- Get current scale
local video_width = mp.get_property_number("width", 0)
local video_height = mp.get_property_number("height", 0)
local display_width = mp.get_property_number("display-width", 0)
local display_height = mp.get_property_number("display-height", 0)
local scale = 1
if video_width > 0 and video_height > 0 then
scale = math.max(display_width / video_width, display_height / video_height)
scale = math.floor(scale * 10) / 10
end
-- Color space details for debugging
local peak = mp.get_property("video-params/sig-peak", "")
local avg_luma = mp.get_property("video-params/light", "")
mp.osd_message(
"RTX Status:\n" ..
"VSR: " .. vsr_status .. " (scale: " .. scale .. "x)\n" ..
"RTX HDR: " .. hdr_status .. "\n" ..
"Content: " .. content_type .. "\n" ..
"Active: " .. active_filters .. "\n" ..
"Output CSP: " .. output_csp .. "\n" ..
"VO: " .. vo .. " / API: " .. gpu_api .. " / HWDec: " .. hwdec .. "\n" ..
"Filter chain: " .. (vf_chain ~= "" and vf_chain or "none") .. "\n" ..
"Peak: " .. peak .. " / Avg Luma: " .. avg_luma,
5
)
end
-- Apply filters automatically on video load
mp.register_event("file-loaded", function()
if autovsr_enabled or autohdr_enabled then
-- Small delay to ensure video properties are loaded
mp.add_timeout(0.1, function()
apply_filters()
mp.observe_property("video-params", "native", apply_filters)
mp.observe_property("vf", "native", apply_filters)
end)
end
end)
-- Keybindings
mp.add_key_binding("ctrl+shift+r", "autovsr", toggle_vsr)
mp.add_key_binding("ctrl+shift+h", "autohdr", toggle_hdr)
mp.add_key_binding("ctrl+shift+s", "rtx_status", show_status)
@drandarov-io
Copy link

mpv-player/mpv#17265

AutoHDR seems to have been fixed only days ago. So you need the latest libmpv.

@44670
Copy link

44670 commented Mar 9, 2026

had to use the below code for it to work for me, in case it is useful for someone: mp.commandv("vf", "append", "@rtx-combined:d3d11vpp=scaling-mode=nvidia:scale=" .. scale .. ":format=x2bgr10:nvidia-true-hdr")

Thanks, the original code doesn't work (HDR not active in NVIDIA App), this works for me.

Windows 11/ RTX 5060Ti / mpv nightly

@CE-Yazeed
Copy link

Everything works right away, main issue is the autoHDR destroys colors and it goes horrible
hdr off
hdr on

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment