Skip to content

fix(engine): hold the last video frame at the inclusive clip end#1563

Closed
calcarazgre646 wants to merge 1 commit into
heygen-com:mainfrom
calcarazgre646:fix/engine-clip-end-frame-visibility
Closed

fix(engine): hold the last video frame at the inclusive clip end#1563
calcarazgre646 wants to merge 1 commit into
heygen-com:mainfrom
calcarazgre646:fix/engine-clip-end-frame-visibility

Conversation

@calcarazgre646

Copy link
Copy Markdown
Contributor

Problem

The FrameLookupTable active set deactivated a video on an exclusive end-bound (globalTime < end), while the runtime keeps an element visible through currentTime <= end (core/runtime/init.ts). So the rendered frame landing exactly on a clip's end went blank, even though the runtime still showed the element on its final frame. That is one blank frame at the end of every clip whose end lands on a frame boundary (e.g. a 2s clip starting at 1.0s in a 30fps render: frame 90 = t 3.0 = end).

The injector hides both the native <video> and the __render_frame__ image with !important when a video is inactive, so the runtime's non-important visibility: visible cannot show through either — the region renders blank for that frame.

Change

Make the active window inclusive of the end (globalTime <= end) to match the runtime, and at t === end serve the last extracted frame, mirroring the runtime holding the element's final frame there. Mid-clip source exhaustion (t < end, the deliberate blank-tail) is unchanged.

This is the same render-vs-runtime boundary alignment as #1339 / #1340, applied to the video frame injector.

Tests

videoFrameExtractor.test.ts: holds the last frame at t === end for a well-matched clip; holds it at the end even when the source is shorter than the window, while the mid-clip tail stays blank (the existing blank-tail test still passes); adjacent clips are both active at a shared boundary, matching the runtime. Full engine suite green (745 tests).

The frame-lookup active set deactivated a video on an exclusive end-bound
(globalTime < end), while the runtime keeps an element visible through
currentTime <= end (core/runtime init.ts). The rendered frame landing
exactly on a clip's end went blank even though the runtime still showed
the element on its final frame: one blank frame at the end of every clip
whose end lands on a frame boundary.

Make the active window inclusive of the end to match the runtime, and at
t === end serve the last extracted frame (the runtime holds the element's
final frame there too). Mid-clip source exhaustion (t < end) stays blank,
unchanged.
@miguel-heygen

Copy link
Copy Markdown
Collaborator

Thanks for catching this — real bug, correct fix. We've incorporated your changes into #1564 with one additional consistency fix (getFrame had the same exclusive bound at line 1006). Closing in favor of that PR. Appreciate the contribution!

@calcarazgre646

Copy link
Copy Markdown
Contributor Author

Thanks for folding it in, and good call on the getFrame alignment. That accessor was the one path I left on the old exclusive bound, so good to have both consistent now.

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.

2 participants