fix(engine): hold the final frame when a video media start is past EOF - #3959
Closed
valeriangalliat wants to merge 1 commit into
Closed
valeriangalliat wants to merge 1 commit into
valeriangalliat wants to merge 1 commit into
Conversation
A non-looping <video> whose planned mediaStart is at or after the last playable frame used to fail extraction with media_start_out_of_range. The browser runtime never fails there: it clamps currentTime and holds the final frame for the whole slot (isHeldVideoTail), so preview and render disagreed on a composition that check and the runtime both accept. The explicit-slot hold already covers a media start inside the file; this extends it to the degenerate case where no source remains. Plan such a clip as a one-frame held tail (the same finalFrameOnly shape a held suffix already uses) instead of throwing. A slot with no interval inside the composition, or a source-bounded slot, is skipped. Looping media keeps the typed failure: the runtime wraps the phase there and a hold would show the wrong frame. The HDR preflight guard narrows to the looping case for the same reason. The offset is not always authored by hand: a media start derived from where a clip becomes visible inside a longer scene lands past the file end once the reveal is later than the clip is long, so render could refuse a window the pipeline planned itself. Fixes heygen-com#3958
miguel-heygen
approved these changes
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
valeriangalliat
added a commit
to ArcadeHQ/hyperframes-next
that referenced
this pull request
Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3958
What
A non-looping
<video>whosedata-media-startis at or past the end of the file now renders as a one-frame held tail (the clip's last frame for the whole slot) instead of failing extraction withmedia_start_out_of_range.The browser runtime already behaves this way: it clamps
currentTimeand holds the final frame (isHeldVideoTail), andcheckpasses the composition. Render was the odd one out. The explicit-slot hold from #2516 covers a media start inside the file; this extends it to the degenerate case where zero seconds of source remain, sodata-media-start="1.9"and"2.1"on a 2 s file behave the same way.How
resolveVideoExtractionWindow: a non-loop past-EOF start returns afinalFrameOnly-shaped window (resolvePastEofHoldWindow) instead of throwing. A source-bounded slot or a slot with no interval inside the composition is skipped, matching the runtime's implicit slot.resolveFinalFrameExtractionWindow:sourceRemainingis floored at one logical frame so the held tail never has a zero or negative duration.-sspreflight guard inextractAllVideoFramesand the HDR preflight narrow to the loop case for the same reason.Tests
videoFrameExtractor.test.ts: hold at source EOF, hold at video-stream EOF when the container continues, hold well past EOF on a later slot, skip when the slot has no interval in the composition, loop still rejected, end-to-end hold throughextractAllVideoFrames.captureHdrResources.test.ts: one-frame hold for a non-loop past-EOF start, null for a source-bounded slot, loop still rejected before HDR budgeting.Repro: https://github.com/ArcadeHQ/hyperframes-repros/tree/patch/media-start-past-eof-hold (
checkclean,renderfails on 0.8.40, passes with this change).