Nodes/XENodes/Save HDR Video
ComfyUI Node

Save HDR Video

Encode your video as 10-bit HDR with the same tone-map math

By xeinherjer-dev·Created 6 months ago·Updated a day ago· 2
Save HDR Video
  • video
  • video
filename_prefixvideo/ComfyUI
format
peak_nits400
itm_knee0.00
itm_exponent1.00
loop_count0
pingpongfalse

If Save HDR Image is the still-photo version, this is the motion picture: same inverse-tone-mapping math, applied to every frame of a VIDEO, encoded as a true HDR file with a 10-bit codec and the PQ (SMPTE ST 2084) transfer curve. It's the node you reach for when you've generated a video and you want it to actually light up an HDR display instead of clamping to SDR. Like its still sibling it's flagged experimental, and it earns the label - but the pipeline is real and model-free: brightness math in PyTorch, then ffmpeg.

How it works, briefly: each frame goes through the same expansion as the image node - sRGB to linear, a soft-knee power-curve lift controlled by itm_knee and itm_exponent, then scaled so SDR white maps to your peak_nits. The expanded frames stream to ffmpeg, which encodes with BT.2020 primaries, the PQ transfer function, and a 10-bit pixel format (yuv420p10le for CPU AV1, p010le for NVENC). Audio rides along - AAC or Opus - because a video with a soundtrack that loses it is a video you immediately regret.

The inputs:

  • video - what you're saving, frames plus optional audio.
  • format - mp4 or webm; each offers av1 (CPU) or av1_nvenc (GPU) with a CRF slider (default 30).
  • peak_nits (100–10000, default 400) - your target peak brightness. Push to 1000 if the target display actually supports it; 400 is a safe default that looks right on more hardware.
  • itm_knee (default 0) and itm_exponent (default 1) - the same expansion controls as the image node. Knee 0 expands everything (punchy but can look overdone), 0.8 keeps midtones and lifts only highlights.
  • loop_count (default 0) and pingpong - repeat frames for mp4/webm, or play forward then backward, for looping animations.
  • audio_codec - aac or opus, with bitrate, when the source has audio.

The video output passes your input straight through, so you can save the HDR copy and keep the original in the graph.

Install is the pack standard:

cd ComfyUI/custom_nodes
git clone https://github.com/xeinherjer-dev/ComfyUI-XENodes.git xenodes

or search "ComfyUI-XENodes" in ComfyUI Manager, then restart. And this is the node where the README's FFmpeg requirement is real: it needs ffmpeg in PATH with AV1 support (libsvtav1), and it will fail loudly with "FFmpeg executable not found" if not. ffmpeg -version to check.

Honest expectations, and there are several. This is slow. CPU AV1 at 10-bit on a batch of frames is a "go make tea" operation; use av1_nvenc if your GPU supports it. It's also video you can't easily see: on an SDR monitor an HDR file renders dim and washed-out, so you can't judge the tone map by eye on most screens - trust the numbers, or check it on the actual display. And the usual experimental caveats apply: play nice with the CRF defaults before chasing quality, and expect that some video players/editors will mis-handle HDR metadata even when the encode is correct. Finally, the pack loads as one unit, so if no XENodes nodes appear after install, check the console for a sibling import failure - SaveAudio needs PyAV's av, and one missing import hides the whole menu.

Categoryxenodes/deprecated

Inputs (8)

NameTypeDefaultDescription
videoVIDEOThe video to save.
filename_prefixSTRINGvideo/ComfyUIThe prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes.
formatCOMBOThe format to save the video as.
peak_nitsFLOAT400100–10000Peak brightness in nits. SDR white (100 nits) will be mapped to this target luminance in HDR.
itm_kneeFLOAT0.000–1Inverse Tone Mapping (Soft-Knee) threshold. 0.0 starts expansion from black. 0.8 preserves SDR midtones and applies expansion to highlights.
itm_exponentFLOAT1.001–10Expansion curve exponent. 1.0 = Linear (punchy/bright), 2.0 = Quadratic (soft/natural), >2.0 = even softer transition.
loop_countINT00–100Loop count. 0 = play once. For mp4/webm, this physically repeats the frames.
pingpongBOOLEANfalsePingpong animation (images only). Plays frames forward then backward.

Outputs (1)

NameTypeDescription
videoVIDEOThe input video.