render: a composition slot's data-duration does not bound the media nested inside it (audio plays past the slot)
Describe the bug
When a nested composition slot is authored with data-start and data-duration but no data-end, render plans the audio and video nested inside that slot to their own authored end, not to the slot's end. The runtime already hides the slot's timed descendants at start + duration (since #1662), so the picture switches to the next scene while the previous scene's sound keeps playing.
Link to reproduction
https://github.com/ArcadeHQ/hyperframes-repros/tree/patch/host-duration-bound
Steps to reproduce
git checkout patch/host-duration-boundnpx [email protected] check(clean)npm run render -- --debug -o out/repro.mp4 --quality draftffmpeg -ss 2 -t 2 -i out/repro.mp4 -vn -af volumedetect -f null -and readmean_volume
The project: root 4s. Slot scene-a is data-start="0" data-duration="2" over a scene whose content is 4s and which holds <audio data-start="0" data-duration="4"> (silent until 1.5s, then a 440 Hz tone). Slot scene-b follows at 2–4s.
Expected behavior
Scene B (2–4s) is silent. The slot ended at 2s, and the runtime already treats it as closed for visibility (scene-a's data-start="2.5" element never paints).
Actual behavior
About −21 dB mean volume in 2–4s: the tone plays over scene B. compiled/summary.json in the producer .debug directory lists scene-a-sound as start 0, end 4. The frame at 3s is correctly scene B, so pixels and audio disagree about where the slot ends.
Where: packages/producer/src/services/renderMediaCollector.ts → resolveHostWindow bounds a host by data-end only (the comment notes a host with just data-duration was unbounded in the older file-tree walk too). compileTimingAttrs stamps data-end on <video>/<audio> tags but not on composition hosts, so a slot authored with data-duration never gets one. Runtime visibility and the runtime media sync both honour data-duration on the host, so preview and render disagree.
Proposed fix: when a host has no data-end, bound it at resolved data-start + data-duration. PR to follow.
Environment
- hyperframes 0.8.40 (latest)
- Node.js v24.19.0, macOS (darwin arm64)
- FFmpeg / FFprobe 8.1.2
- Chrome headless shell 152.0.7977.54 (puppeteer cache)
npx hyperframes doctorfrom the repro checkout: all required checks pass; optional whisper-cpp, Kokoro, MusicGen and Docker not installed.
Additional context
With the proposed fix applied, the same render gives −91 dB (digital silence) in 2–4s and is otherwise identical.
Source: heygen-com/hyperframes