HDR to SDR Movie Converter logo HDR to SDR Movie Converter
FFmpeg · libplacebo/Vulkan · HandBrakeCLI

Turn any screen into an HDR screen. Simple enough for Grandma.

A desktop tone-mapping tool with FFmpeg and HandBrake support, a wide range of curves, and true BT.2390 on the GPU. 10-bit and 12-bit output included, free.

HDR to SDR Movie Converter app window, showing Files, Source analysis, Progress and Controls on the left, and Conversion settings on the right.
Why it matters

Same source — different results

What the movie actually looks like depends entirely on how it's done — no conversion at all, a media player's own quick guess, or a real BT.2390 pass.

Raw HDR video played back on a display without HDR support — washed out, flat, low-contrast image.
No conversion

Raw HDR, no conversion

Playing an untouched HDR file on a display or projector that doesn't understand HDR — the PQ/HLG curve is being shown as if it were SDR, so everything looks grey, flat, and washed out.

The same HDR video auto-tone-mapped by a media player like VLC — crushed highlights, shifted color.
Auto tone-map

Auto-converted by a media player

Players like VLC apply their own quick tone-map so playback is at least watchable — usually a blunt, fixed curve that clips highlights or shifts color, not a deliberate BT.2390 pass with a curve you chose.

The same HDR video correctly converted to SDR with this app's BT.2390 GPU tone mapping — balanced highlights and accurate color.
Real BT.2390

Proper BT.2390 tone mapping

The actual ITU-R BT.2390 EETF, run on the GPU via libplacebo — controlled highlight rolloff and accurate color, output as a real SDR file ready for any standard display.

Backends

Three ways to tone-map. Pick what matches your hardware.

Same source video, three genuinely different pipelines. Nothing is hidden behind an "auto" button — the backend and curve you choose are the exact ones that run.

CPU · Standard

Standard FFmpeg

The classic tonemap filter. Fast, works everywhere FFmpeg does, no GPU required.

  • Hable, Reinhard, Mobius curves
  • Pro mode adds Linear, Gamma, Clip, and a direct "None" pass
GPU · Vulkan

libplacebo / BT.2390

Runs the real ITU-R BT.2390 EETF on the GPU via libplacebo, the same curve reference HDR-to-SDR grades are built around.

  • BT.2390 by default
  • Pro mode unlocks BT.2446A, ST2094-10, ST2094-40 (HDR10+), and Auto
Optional

HandBrakeCLI

An alternate encode path through HandBrakeCLI for cases where its own pipeline behaves better on a given source.

  • Same resolution/encoder controls
  • Own progress parsing, shown live in Activity
Controls

Everything a real conversion needs — done right.

Built around the parts of a tone-mapping job that actually go wrong on real footage: the wrong curve, the wrong encoder, or a process that steals the whole machine while it runs.

Resolution presets

Source (no scaling), 4K, 1440p, 1080p, 720p, or 480p. Scaling is height-driven, with width computed automatically so the source's aspect ratio is never stretched.

Analyzes automatically

Pick a source and it's read immediately — transfer characteristics, bit depth, duration, HDR10+/Dolby Vision metadata — with a curve suggested for that specific file. The SDR output path is filled in for you, and dropping a video file anywhere on the window works the same as Browse.

Live Preview

A real decoded, tone-mapped frame from your source that updates as you change settings, with a shadow/highlight clipping check so a curve crushing detail shows up before a full encode. View it full size or save the frame straight to disk.

Live bitrate estimate

Updates automatically as quality, resolution, or encoder change, so a surprising CRF/resolution combo is visible before you hit Start.

Curve tooltips

Hover any tone-mapping curve for a plain-language rundown of what it actually trades off — not marketing copy.

Encoder choice

x264/x265 on CPU, or hardware encode via NVIDIA NVENC, AMD AMF, or Apple VideoToolbox, in H.264 or H.265.

10-bit & 12-bit output

Free, no license required, no separate build. 10-bit works with any H.265 encoder (CPU or hardware); 12-bit is available via libx265 on CPU — the app only shows encoders that actually support the bit depth you picked.

Pro mode

Opens the full CRF/CQ range (0–51), a brightness offset control, and the extra tone-map curves — kept out of the way until you ask for them.

Hardware-accelerated decode

CUDA / DXVA2 / VideoToolbox decode for the FFmpeg backend, so the GPU is doing the reading as well as the tone-mapping.

Process priority & CPU cores

Efficiency, Balanced, or Performance, plus a live CPU-core limit — both applied at Start and adjustable while a conversion is running, so a long batch doesn't have to lock up the rest of your machine.

Activity & System

A collapsible live log streams the actual FFmpeg/HandBrake output and progress; a System panel reports what's detected on your system — FFmpeg, Vulkan, HandBrakeCLI — before you hit convert.

One-click setup on Windows

Missing FFmpeg or HandBrakeCLI is installed via winget from inside the app — from the System panel, or the "Quick install" shortcut right next to it — with install output streamed into Activity.

HDR to SDR Movie Converter icon
Download

Get the app

A Windows build if you just want to run it, or the source if you're on macOS/Linux or want to read the code first.

Windows

Windows (.exe)

Single-file build, no Python required. FFmpeg is still needed separately — or install it in-app via winget.

Always the newest release · Windows 10/11

Source

Source code

Requires Python 3.10+ and pip install -r requirements.txt. Runs on Windows, macOS, and Linux.

MIT licensed · main branch

Documentation

Install & usage guide

The app is a single PySide6 script. No installer, no background service — you run it, it shells out to FFmpeg (and optionally HandBrakeCLI) directly.

Requirements

What needs to be on the machine before you launch it.

ComponentNeeded for
Python 3.10+Running the app itself
PySide6The Qt-based UI
FFmpeg (full/GPL build, with libx264 + libx265)Standard and GPU tone-mapping backends
Vulkan-capable GPU + driversThe libplacebo/BT.2390 backend specifically
HandBrakeCLI (optional)The HandBrake backend
psutil (optional)Live pause/resume, CPU-core control, and CPU/GPU resource stats

Dependencies & licensing

This app doesn't bundle FFmpeg or HandBrakeCLI — they're installed on your own machine, straight from their authors' official channels, via winget.

ToolSourcewinget package IDLicense
FFmpeggyan.dev full buildGyan.FFmpegGPLv3
HandBrakeCLIHandBrake official releaseHandBrake.HandBrake.CLIGPLv2

Both are independent open-source projects — full credit to their authors and contributors. This app is a GUI front end that shells out to them as separate processes; it doesn't modify, link against, or redistribute their code, and each keeps its own license regardless of this app's own MIT license. Prefer to install them yourself instead of the in-app installer? That works too — the app just looks for ffmpeg, ffprobe, and HandBrakeCLI on your PATH.

Install & run

Three commands, then you're looking at the window.

# 1. Get the script and its Python dependencies
pip install PySide6 psutil

# 2. Make sure FFmpeg is on your PATH
ffmpeg -version

# 3. Launch
python hdr_to_sdr_gui_qt.py
Windows: if FFmpeg or HandBrakeCLI aren't found, open the System panel and use "Install missing (winget)" instead of installing them by hand.

Basic workflow

From HDR source file to SDR output.

  1. Pick the source file. Any HDR container FFmpeg can read — analysis runs automatically (transfer function, bit depth, HDR10+/Dolby Vision metadata, and a suggested curve), and the SDR output path is filled in for you. Dragging a file onto the window works the same as Browse.
  2. Choose a backend and curve. BT.2390 on GPU is the sane default; switch to Standard FFmpeg if you don't have a Vulkan-capable GPU. Hover any curve for what it actually trades off.
  3. Set resolution, encoder, and bit depth. Leave resolution on "Source" to keep the original frame size and aspect ratio, or pick a preset to downscale during the same pass.
  4. Adjust quality, or enable Pro mode for full CRF/CQ range and a brightness offset. Check Live Preview — it shows a real tone-mapped frame and flags shadow/highlight clipping — and the live bitrate estimate before committing.
  5. Convert, and watch progress and the live FFmpeg/HandBrake output in Activity. Pause/resume, CPU-core limits, and process priority can all be adjusted while it runs.

Choosing a curve

All of these are real, documented FFmpeg/libplacebo tone-mapping options — nothing here is invented.

CurveBackendWhen to reach for it
BT.2390GPUDefault choice — the reference EETF most HDR-to-SDR grades target
HableCPUFilmic rolloff, no GPU needed
Reinhard / MobiusCPUSofter highlight rolloff alternatives to Hable
BT.2446AGPU · ProBroadcast-oriented alternative to BT.2390
ST2094-10 / ST2094-40GPU · ProDynamic tone-mapping; ST2094-40 uses HDR10+ metadata when present
Linear / Gamma / Clip / NoneCPU · ProDiagnostic or manual-grading passes, not general use

Troubleshooting

The System panel is the first stop — it reports exactly what was detected before you file this as a bug.

  • BT.2390 (GPU) option greyed out — no Vulkan-capable device was detected; use a Standard FFmpeg curve instead.
  • HandBrakeCLI backend missing — it's optional and only appears once HandBrakeCLI is found on your PATH.
  • Conversion feels like it's stealing the machine — drop Process priority to Efficiency.
  • "Encoder unavailable" for CPU · H.264/H.265 — you likely have an LGPL/"essentials" FFmpeg build without libx264/libx265. Use "Install missing (winget)" in the System panel, which installs the full GPL build automatically.