dovi_tool
37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0dovitool is a CLI tool combining multiple utilities for working with Dolby Vision.
dovi_tool is a command-line tool by quietvoid for working with Dolby Vision. Its main job in an encoding workflow is moving the RPU — the per-frame Dolby Vision metadata — from a source to a new encode, converting the profile on the way when needed. It also inspects, edits, plots and generates RPUs. It works on HEVC (raw Annex B streams, or Matroska files with an HEVC track); it doesn’t decode or encode video.
The same repository contains the dolby_vision Rust crate, also built as the C library libdovi, which other tools use for RPU parsing. See HDR formats for what the profiles mean.
Install
Section titled “Install”Download a binary from the GitHub releases: builds are provided for x86-64 and ARM64 Linux (static musl), x64 and ARM64 Windows, and universal macOS. To build from source you need Rust 1.88 or newer and, on Linux, fontconfig (or build with --no-default-features --features internal-font):
git clone https://github.com/quietvoid/dovi_tool.gitcd dovi_toolcargo build --releaseKeep Dolby Vision through a re-encode
Section titled “Keep Dolby Vision through a re-encode”-
Extract the RPU. dovi_tool reads Matroska directly:
Terminal window dovi_tool extract-rpu input.mkv -o RPU.binFor a profile 7 source (UHD Blu-ray), convert to 8.1 while extracting, since single-layer 8.1 is what you are going to encode:
Terminal window dovi_tool -m 2 extract-rpu input.mkv -o RPU.binFor MP4 or other containers, pipe the stream through FFmpeg:
Terminal window ffmpeg -i input.mp4 -c:v copy -f hevc - | dovi_tool extract-rpu - -o RPU.bin -
Check what you have:
dovi_tool info -i RPU.bin --summaryprints the frame count, profile, scene count, L5 offsets and L6 values. -
Encode the HDR10 base layer at the same frame count. x265 can write the RPU itself:
Terminal window x265 --input video.y4m --output-depth 10 --crf 18 --preset slow --colorprim bt2020 --transfer smpte2084 --colormatrix bt2020nc \--master-display "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)" --max-cll "1000,400" \--vbv-maxrate 40000 --vbv-bufsize 50000 --dolby-vision-profile 8.1 --dolby-vision-rpu RPU.bin -o output.hevcx265 refuses Dolby Vision without VBV settings (it needs them to write HRD information); pick values that suit the level you target. Take the mastering-display and MaxCLL values from the source.
-
Or encode with anything that outputs HEVC and inject the RPU afterwards:
Terminal window dovi_tool inject-rpu -i output.hevc --rpu-in RPU.bin -o injected.hevc -
Mux.
mkvmerge -o final.mkv injected.hevcwrites the Dolby Vision configuration record automatically. For MP4 with FFmpeg add-strict unofficial, or the configuration box is left out and players treat the file as plain HDR10.
The RPU must line up with the new video frame for frame. If you cut, trim or drop frames, edit the RPU the same way first (see edit an RPU). If you crop away letterbox bars, add the global --crop option when extracting, which sets the L5 active-area offsets to zero.
Conversion modes
Section titled “Conversion modes”The global -m/--mode option rewrites the RPU during extract-rpu, convert, demux and mux. inject-rpu ignores global options.
| Mode | Result |
|---|---|
| none | RPU copied untouched |
0 | Parsed and rewritten without changes |
1 | Profile 7 FEL converted to MEL |
2 | Profile 8.1; luma/chroma mapping removed for profile 7 FEL |
3 | Profile 5 converted to 8.1 |
4 | Profile 8.4 |
5 | Profile 8.1, mapping preserved (the old mode 2) |
Mode 2 is the usual choice for profile 7. With a FEL source the enhancement layer carries real picture data, so dropping it and using a converted RPU gives a result that is close to, but not the same as, the full dual-layer image; with MEL nothing visible is lost. Mode 3 changes only the RPU: a profile 5 base layer is in Dolby’s IPTPQc2 color space, not HDR10, so the video itself must also be converted (for example decoded through libplacebo) for the result to be valid 8.1.
Other commands
Section titled “Other commands”| Command | What it does |
|---|---|
info -i RPU.bin --summary / --frame N | Summary, or one frame’s RPU as JSON (frames count from 0) |
export -i RPU.bin -d all=RPU.json | Export all RPUs as JSON; -d scenes=scenes.txt exports scene-cut frames, level5=L5.json the active-area edits |
plot RPU.bin -o L1.png | Plot L1 brightness; -p l2 or -p l8 plots trims |
editor -i RPU.bin -j edits.json -o out.bin | Remove or duplicate frames, change active areas, scene cuts or L6 values |
generate -j config.json -o RPU.bin | Generate a profile 8.1 or 8.4 RPU from a JSON config, a Dolby Vision XML, an HDR10+ JSON (--hdr10plus-json) or a madVR measurement file |
convert, demux, mux | Convert the RPU in place, split a dual-layer stream into BL.hevc and EL.hevc, or interleave them again |
remove | Strip the RPU and enhancement layer, leaving the HDR10 base layer in BL.hevc |
Other global options: --drop-hdr10plus removes HDR10+ SEI messages when writing HEVC, and --start-code annex-b writes variable-length start codes like x265 instead of always four bytes. extract-rpu accepts -l N to stop after N frames and -t N to pick a Matroska track. convert, demux and remove on Matroska input are experimental in 2.3.4.
Edit an RPU
Section titled “Edit an RPU”The editor takes a JSON file. Frame ranges are inclusive and count from 0; removals run before duplications. To drop the first 40 frames of metadata, for example after trimming 40 frames from the start of the video:
{ "remove": ["0-39"]}To repeat metadata for inserted frames, use "duplicate": [{ "source": 100, "offset": 100, "length": 24 }]. The full schema, including active-area presets and L6 replacement, is in editor.md.