Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

HDR render composites elements without data-start under the HDR video (captions and overlays vanish)

Open
#5,102 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Dante-dan is already working on this.

Since Oct 7, 2026.

  • #5183 by @Dante-dan — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
58/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
html, typescript
Domain
backend

Research direction

Start by locating the bundled engine’s queryElementStacking and groupIntoLayers functions mentioned in the issue, then trace the HDR layered-render path and its existing tests. Use the provided HLG reproduction to verify that an untimed caption above the video remains visible in HDR, while the timed-caption control still works; also check that --sdr behavior is unchanged.

Written by the indexing model from the issue text.

Description

Describe the bug

When a render takes the HDR layered path (any video tagged HLG or PQ, which includes every iPhone clip shot with HDR on), elements that have no data-start attribute are composited underneath the native HDR video, whatever their z-index. In the output the video covers them: captions, titles and overlays disappear. Preview and --sdr renders are correct.

Cause, from reading the bundled engine: queryElementStacking builds the layer list from document.querySelectorAll("[data-start]") only, and groupIntoLayers sorts that list by effective z-index. An element without data-start never gets its own entry, so it never lands in a DOM layer above the HDR video. It only shows up as part of a layer below it (or the base), and the HDR video frame is then blitted over it.

This is easy to hit in practice: the desktop app's own takeover-explainer format drives its captions, hook titles, screenshot cards and logos with GSAP on plain elements (#tx-caps at z-index: 4, #tx-hook at 5, #tx-cards at 3, and so on, none with data-start), above a .tx-plate-wrap video at z-index: 2. Shot on an iPhone, the exported reel loses all of them while the preview looks right. The desktop Export has no SDR option, so a desktop user cannot work around it without re-encoding their footage.

Minimal reproduction
mkdir -p repro/assets && cd repro
# 3 s test pattern carrying HLG tags (tags alone switch the render to HDR)
ffmpeg -f lavfi -i "testsrc2=s=540x960:r=30:d=3" \
  -vf "setparams=color_primaries=bt2020:color_trc=arib-std-b67:colorspace=bt2020nc,format=yuv420p" \
  -c:v libx264 -x264-params "colorprim=bt2020:transfer=arib-std-b67:colormatrix=bt2020nc" \
  -color_primaries bt2020 -color_trc arib-std-b67 -colorspace bt2020nc assets/hlg.mp4

index.html:

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><title>hdr overlay repro</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<style>
  html, body { margin: 0; padding: 0; background: #000; }
  #root { position: relative; width: 540px; height: 960px; overflow: hidden; background: #000; }
  .wrap { position: absolute; inset: 0; z-index: 2; }
  .wrap video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  #caps { position: absolute; inset: 0; z-index: 4; }
  .cap { position: absolute; left: 70px; top: 700px; width: 400px; height: 120px; background: #FF00FF; }
</style></head>
<body>
<div id="root" data-composition-id="main" data-width="540" data-height="960" data-duration="3" data-fps="30">
  <div class="wrap"><video id="plate" data-start="0" data-duration="3" data-track-index="0" src="assets/hlg.mp4" muted playsinline></video></div>
  <div id="caps"><div id="cap" class="cap"></div></div>
</div>
<script>window.__timelines = window.__timelines || {}; window.__timelines["main"] = gsap.timeline({ paused: true });</script>
</body></html>

Control: give the caption timing (<div id="cap" class="cap clip" data-start="0" data-duration="3" data-track-index="1"></div>) and the same HDR render is correct.

Steps to reproduce
  1. hyperframes render . -o auto.mp4 --fps 30 (auto picks HDR: log shows "effectiveHdr":"hlg" and capture_hdr_layered)
  2. hyperframes render . -o sdr.mp4 --fps 30 --sdr
  3. Sample the caption area at t=1.5 s in both, e.g. ffmpeg -ss 1.5 -i auto.mp4 -frames:v 1 -vf "format=rgb24,crop=1:1:270:760" -f rawvideo - | xxd -p
Expected behavior

The magenta caption (#caps, z-index: 4) draws above the video (.wrap, z-index: 2) in both renders, as it does in preview and in --sdr. Elements without data-start take part in the stacking order like any other element.

Actual behavior
auto (effectiveHdr hlg)   caption pixel #020ffc   <- test pattern: the video covers the caption
--sdr                     caption pixel #fc00fd   <- caption on top
caption with data-start   caption pixel #ff00fe   <- correct in HDR too

Things I ruled out on the way, each rendered correctly in HDR as long as the overlay had data-start: a transformed/scaled video wrapper, clip-path: inset(...) and filter on the wrapper, a second video sharing the same source at opacity 0, a z-index: 1 background layer under the video, and overlays that start opacity: 0; visibility: hidden and are revealed with autoAlpha. On the real takeover-explainer reel, removing the second video, the clip-paths, the filters or the transforms (one at a time) did not help either; adding nothing but HLG tags to the plate is what breaks it, and converting the plate to bt709 fixes it.

Environment
HyperFrames desktop 0.1.0 (build b269), bundled hyperframes CLI + @hyperframes/* 0.8.133
macOS 27.0.1 (26A434), Apple M1 Pro (arm64)
Rendered with the desktop's own bundled CLI and ffmpeg (no `npx hyperframes doctor`: desktop app)
Additional context

Possible fixes:

  • Build the stacking list from every rendered element in the composition root (or from paint order), not only [data-start], so untimed overlays get their own DOM layer above or below each HDR video.
  • Failing that, detect DOM that is not covered by [data-start] stacking and fall back to SDR (or warn loudly) instead of silently hiding it.
  • Give the desktop Export a Standard (SDR) option, so a desktop user has a way out.

Related, both closed: #1952 (HDR layered path froze timed overlays) and #3591 (HDR layered path ignored sub-composition windows). Same path, different defect.

Workaround for anyone hitting this: convert the footage to SDR before exporting, for example zscale=min=bt2020nc:pin=bt2020:tin=bt709:rin=tv:m=bt709:p=bt709:t=bt709:r=tv,format=yuv420p with bt709 output tags, or render from the CLI with --sdr.

Dominant language
TypeScript
Stars
54.1k
Forks
4.9k
Avg merge
7h 19m
Merged PRs (30d)
746

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from heygen-com/hyperframes

All issues in heygen-com/hyperframes

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.