# hdr10plus_tool

Canonical URL: https://encode.wiki/tools/utilities/hdr10plus_tool/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): f5e217ef28373c65a28ffce2461d6a4eaa4d9f4a79c6ce72cc379a5bc27c6521

> **Repository:** [quietvoid/hdr10plus_tool](https://github.com/quietvoid/hdr10plus_tool). CLI utility to work with HDR10+ in HEVC files. Latest release: [1.7.2](https://github.com/quietvoid/hdr10plus_tool/releases/tag/1.7.2), Dec 27, 2025. Last commit: Apr 27, 2026. License: MIT. Stars: 462.

hdr10plus_tool is a command-line tool by quietvoid for HDR10+ metadata in HEVC. It extracts the per-frame SMPTE ST 2094-40 metadata to a JSON file, injects it into another HEVC stream, removes it, edits frame ranges and plots it. It was previously called `hdr10plus_parser`. It works on raw HEVC streams and on Matroska files with an HEVC track; it doesn't handle AV1. See [HDR formats](/hdr/#hdr10) for what HDR10+ is.

## Install

Download a binary from the [GitHub releases](https://github.com/quietvoid/hdr10plus_tool/releases) (x86-64 and ARM64 Linux, x64 and ARM64 Windows, universal macOS), or build with Rust 1.85 or newer. On Linux the build needs fontconfig, or use `--no-default-features --features internal-font`:

```sh
git clone https://github.com/quietvoid/hdr10plus_tool.git
cd hdr10plus_tool
cargo build --release
```

## Keep HDR10+ through a re-encode

1. Extract the metadata. Matroska is read directly:

   ```sh
   hdr10plus_tool extract input.mkv -o metadata.json
   ```

   For MP4 or other containers, pipe the stream through FFmpeg:

   ```sh
   ffmpeg -i input.mp4 -c:v copy -f hevc - | hdr10plus_tool extract -o metadata.json -
   ```

2. Encode with x265 and give it the JSON. x265 writes the HDR10+ SEI for each frame, but only if it was built with `ENABLE_HDR10_PLUS`, which is off by default in x265's CMake files:

   ```sh
   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" \
     --dhdr10-info metadata.json -o output.hevc
   ```

   From FFmpeg the same option goes through `-x265-params dhdr10-info=metadata.json`. Without it, FFmpeg's libx265 encoder drops HDR10+.

3. Or inject into any finished HEVC stream:

   ```sh
   hdr10plus_tool inject -i output.hevc -j metadata.json -o injected.hevc
   ```

4. Confirm it worked with `hdr10plus_tool --verify extract injected.hevc`, which prints `Dynamic HDR10+ metadata detected.` and exits.

The JSON has one entry per frame. If the new encode has a different number of frames or a different start point, adjust the metadata with the editor first.

## Commands

| Command | What it does |
| --- | --- |
| `extract INPUT -o metadata.json` | Extract metadata to JSON, with scene information compatible with Samsung's tools. Without `-o` it only checks for metadata. |
| `inject -i in.hevc -j metadata.json -o out.hevc` | Insert HDR10+ SEI messages before each frame's slices |
| `remove INPUT -o out.hevc` | Remove HDR10+ SEI messages, leaving plain HDR10 |
| `editor metadata.json -j edits.json -o new.json` | Remove or duplicate frames in the metadata |
| `plot metadata.json -o plot.png` | Plot brightness per frame; `-p` picks the peak source (`histogram`, `histogram99`, `max-scl`, `max-scl-luminance`), `-s`/`-e` a frame range |

Global options: `--verify` only checks whether the input contains HDR10+; `--skip-validation` skips the profile-conformity check, for metadata that fails it but that you still want to extract.

The editor JSON uses inclusive frame ranges; removals run before duplications:

```json
{
  "remove": ["0-39"],
  "duplicate": [{ "source": 100, "offset": 100, "length": 24 }]
}
```

## Wrong metadata order on some discs

A few retail discs were authored with the metadata inserted in decode order instead of presentation order, so with B-frames the metadata ends up on the wrong frames. The tell-tale sign is in the extracted JSON: many scenes in `SceneFrameNumbers` only one to three frames long, and `SceneFirstFrameIndex` values that don't line up with the cuts in the video. For those files extract with `--skip-reorder`. Don't use it on correctly authored streams.

## Related tools

[dovi_tool](/tools/utilities/dovi_tool/) can generate a Dolby Vision RPU from an HDR10+ JSON (`dovi_tool generate --hdr10plus-json`) and can strip HDR10+ from a stream while writing with `--drop-hdr10plus`.
