Skip to content

fix(engine): hold the final frame when a video media start is past EOF - #3959

Closed
valeriangalliat wants to merge 1 commit into
heygen-com:mainfrom
valeriangalliat:fix/hold-past-eof-media-start
Closed

valeriangalliat wants to merge 1 commit into
heygen-com:mainfrom
valeriangalliat:fix/hold-past-eof-media-start

Conversation

@valeriangalliat

Copy link
Copy Markdown
Contributor

Fixes #3958

What

A non-looping <video> whose data-media-start is 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 with media_start_out_of_range.

The browser runtime already behaves this way: it clamps currentTime and holds the final frame (isHeldVideoTail), and check passes 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, so data-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 a finalFrameOnly-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: sourceRemaining is floored at one logical frame so the held tail never has a zero or negative duration.
  • Looping media keeps the typed failure: the runtime wraps the phase there, so there is no single frame to hold. The FFmpeg -ss preflight guard in extractAllVideoFrames and 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 through extractAllVideoFrames.
  • 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 (check clean, render fails on 0.8.40, passes with this change).

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
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
valeriangalliat deleted the fix/hold-past-eof-media-start branch September 15, 2026 19:49
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
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.

render refuses a <video> whose data-media-start is past the end of the file (media_start_out_of_range) while the runtime holds its last frame

2 participants