Skip to content

Instantly share code, notes, and snippets.

@anthonybaldwin
Forked from natyusha/autovsr.lua
Last active July 12, 2025 05:04
Show Gist options
  • Save anthonybaldwin/1e49b28b49babf64f159cb793c506333 to your computer and use it in GitHub Desktop.
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment