Describe the bug
Nested compositions that reuse the same media element id are legal per file and lint-clean. At export, those files are inlined into one document. Id-keyed stages of the media pipeline then collide: extract/dedupe collapses to one entry, and frame injection resolves document.getElementById(id) to the first match in document order. The visible scene’s <video> never receives frames — scene chrome still paints; footage does not.
Preview often looks correct because each scene loads in isolation (no single inlined document).
Link to reproduction
https://github.com/ArcadeHQ/hyperframes-repros/tree/patch/unique-media-render-keys
Steps to reproduce
- Clone https://github.com/ArcadeHQ/hyperframes-repros and check out
patch/unique-media-render-keys.
- Run
npx hyperframes lint (expect 0 errors — duplicate ids across files are allowed).
- Preview / editor: both scenes show the long-take (SMPTE bars).
- Run
npm run render (or npx hyperframes@0.8.3 render -f 10).
- Watch the compile log:
videoCount: 1 (should be 2). Open the MP4: green panel then purple panel (scene backgrounds + labels), no color bars.
The project has two 3s nested scenes that each declare <video id="clip"> with different data-media-start (5 vs 50).
Expected behavior
Both halves show footage (different source slices). Extract should report two videos. Inject should target each scene’s own element. It should match the preview.
Actual behavior
On hyperframes@0.8.3:
videoCount: 1, totalFramesExtracted: 30 at 10fps (one 3s window, not two).
- Rendered MP4 is scene chrome only (green → purple). Source frames at 5s / 50s are SMPTE color bars.
Environment
✓ Version 0.8.3 (latest)
✓ Node.js v24.19.0 (darwin arm64)
✓ CPU 10 cores · Apple M1 Pro @ 2400MHz
✓ Memory 16.0 GB total · 3.0 GB available
✓ Disk 345.3 GB free
✓ Frames cache /var/folders/bl/c4hk6r7n34g1d81txd99gsgr0000gn/T/hyperframes-extract-cache-501 · 345.3 GB free at /var/folders/bl/c4hk6r7n34g1d81txd99gsgr0000gn/T/hyperframes-extract-cache-501 · default
✓ Archive extractor unzip
✓ Environment Native terminal
✗ whisper-cpp Not found (optional — needed for transcription)
brew install whisper-cpp
✗ TTS (Kokoro) Not installed (optional — local voice fallback)
pip install kokoro-onnx soundfile
✗ BGM (MusicGen) Not installed (optional — local music fallback)
pip install transformers torch soundfile numpy
✓ FFmpeg ffmpeg 8.1.2 at /opt/homebrew/bin/ffmpeg
✓ FFprobe ffprobe 8.1.2 at /opt/homebrew/bin/ffprobe
✓ Chrome cache: /Users/val/.cache/puppeteer/chrome-headless-shell/mac_arm-150.0.7871.24/chrome-headless-shell-mac-arm64/chrome-headless-shell
✗ Docker Not found
https://docs.docker.com/get-docker/
✗ Docker running Not running
Start Docker Desktop or run: sudo systemctl start docker
Describe the bug
Nested compositions that reuse the same media element
idare legal per file and lint-clean. At export, those files are inlined into one document. Id-keyed stages of the media pipeline then collide: extract/dedupe collapses to one entry, and frame injection resolvesdocument.getElementById(id)to the first match in document order. The visible scene’s<video>never receives frames — scene chrome still paints; footage does not.Preview often looks correct because each scene loads in isolation (no single inlined document).
Link to reproduction
https://github.com/ArcadeHQ/hyperframes-repros/tree/patch/unique-media-render-keys
Steps to reproduce
patch/unique-media-render-keys.npx hyperframes lint(expect 0 errors — duplicate ids across files are allowed).npm run render(ornpx hyperframes@0.8.3 render -f 10).videoCount: 1(should be 2). Open the MP4: green panel then purple panel (scene backgrounds + labels), no color bars.The project has two 3s nested scenes that each declare
<video id="clip">with differentdata-media-start(5 vs 50).Expected behavior
Both halves show footage (different source slices). Extract should report two videos. Inject should target each scene’s own element. It should match the preview.
Actual behavior
On hyperframes@0.8.3:
videoCount: 1,totalFramesExtracted: 30at 10fps (one 3s window, not two).Environment