Skip to content

dovi_tool

currentMigrated from docs/utilities/dovi_tool.mdx at 37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0

dovitool is a CLI tool combining multiple utilities for working with Dolby Vision.

Latest release
2.3.4
Last commit
License
MIT
Stars
1,023

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.

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):

Terminal window
git clone https://github.com/quietvoid/dovi_tool.git
cd dovi_tool
cargo build --release
  1. Extract the RPU. dovi_tool reads Matroska directly:

    Terminal window
    dovi_tool extract-rpu input.mkv -o RPU.bin

    For 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.bin

    For 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
  2. Check what you have: dovi_tool info -i RPU.bin --summary prints the frame count, profile, scene count, L5 offsets and L6 values.

  3. 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.hevc

    x265 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.

  4. 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
  5. Mux. mkvmerge -o final.mkv injected.hevc writes 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.

The global -m/--mode option rewrites the RPU during extract-rpu, convert, demux and mux. inject-rpu ignores global options.

ModeResult
noneRPU copied untouched
0Parsed and rewritten without changes
1Profile 7 FEL converted to MEL
2Profile 8.1; luma/chroma mapping removed for profile 7 FEL
3Profile 5 converted to 8.1
4Profile 8.4
5Profile 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.

CommandWhat it does
info -i RPU.bin --summary / --frame NSummary, or one frame’s RPU as JSON (frames count from 0)
export -i RPU.bin -d all=RPU.jsonExport all RPUs as JSON; -d scenes=scenes.txt exports scene-cut frames, level5=L5.json the active-area edits
plot RPU.bin -o L1.pngPlot L1 brightness; -p l2 or -p l8 plots trims
editor -i RPU.bin -j edits.json -o out.binRemove or duplicate frames, change active areas, scene cuts or L6 values
generate -j config.json -o RPU.binGenerate 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, muxConvert the RPU in place, split a dual-layer stream into BL.hevc and EL.hevc, or interleave them again
removeStrip 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.

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.