Skip to content

feat(engine): add HDR video output pipeline#265

Open
vanceingalls wants to merge 1 commit intofix/mixed-hdr-sdr-video-normalizationfrom
fix/hdr-output-pipeline
Open

feat(engine): add HDR video output pipeline#265
vanceingalls wants to merge 1 commit intofix/mixed-hdr-sdr-video-normalizationfrom
fix/hdr-output-pipeline

Conversation

@vanceingalls
Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls commented Apr 14, 2026

Summary

Adds the ability to render HDR video output (H.265 10-bit, BT.2020) from HyperFrames compositions. When the renderer detects HDR source video, it automatically switches to the HDR output pipeline — no flags needed.

What it does

  • Auto-detection — Probes each video source with ffprobe. If any has bt2020/PQ/HLG color metadata, the output switches to H.265 10-bit with correct color tags. SDR-only compositions are unaffected (H.264, bt709).
  • HLG pass-through — Native HLG pixels from FFmpeg extraction are piped directly to the encoder without conversion. This avoids brightness loss from HLG→linear→PQ conversion (which requires an OOTF system gamma we can't reliably apply).
  • Encoder HDR support — Both chunk and streaming encoders accept HDR presets: libx265, yuv420p10le, BT.2020 color primaries, hvc1 codec tag (required for Apple playback).
  • WebGPU HDR capture (gated) — A complete WebGPU float16 readback pipeline is implemented and tested but gated behind headed Chrome (headless doesn't expose WebGPU). Ready for future use with WebGPU canvas content.
  • HDR utilitiesdetectTransfer() (PQ vs HLG), getHdrEncoderColorParams(), analyzeCompositionHdr(). 15 unit tests.

Key design decisions

Decision Why
No --hdr flag SDR content encoded as HDR causes orange shift in browsers. Auto-detect eliminates this.
HLG pass-through (not HLG→PQ) Conversion loses brightness without OOTF. Pass-through matches source exactly.
hvc1 codec tag Apple QuickTime requires hvc1 (not hev1) for HEVC playback.
1-hour streaming timeout HDR capture at ~6fps needs more time than the default 10-minute FFmpeg timeout.

Files changed

File What changed
packages/engine/src/utils/hdr.ts NEW — HDR detection, transfer types, encoder params (15 tests)
packages/engine/src/services/hdrCapture.ts NEW — WebGPU readback, HLG conversion, PQ encode
packages/engine/src/services/streamingEncoder.ts HDR presets, raw rgb48le input, color tags
packages/engine/src/services/chunkEncoder.ts HDR presets, conditional color tags
packages/producer/src/services/renderOrchestrator.ts Auto-detection loop, HDR pass-through capture path

How to test

Render a composition with an HDR video source. The output should be H.265 10-bit with HDR metadata visible in ffprobe (bt2020, arib-std-b67 or smpte2084). Plays correctly in QuickTime and on HDR displays.

Stack position

2 of 6 — Stacked on #258 (SDR/HDR normalization). Provides the encoder infrastructure that phases 1-5 build on.

🤖 Generated with Claude Code

Copy link
Copy Markdown
Collaborator Author

vanceingalls commented Apr 16, 2026

Auto-detect HDR sources via ffprobe, switch to H.265 10-bit with
BT.2020/HLG metadata. HLG pass-through (no conversion), hvc1 codec
tag for Apple playback, 1-hour streaming timeout for HDR. WebGPU
float16 readback pipeline implemented and tested but gated behind
headed Chrome. HDR utilities with 15 unit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vanceingalls vanceingalls force-pushed the fix/hdr-output-pipeline branch from 1a45995 to ffc3b12 Compare April 17, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant