Skip to content

fix(engine): a video clip starting between frames shows its media on the right frame - #6759

Merged
miguel-heygen merged 7 commits into
mainfrom
fix/video-offgrid-start
Oct 30, 2026
Merged

miguel-heygen merged 7 commits into
mainfrom
fix/video-offgrid-start

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #6753

What

A <video> clip whose data-start falls between frames (or a hair before one) now shows source frame N at output frame N, instead of one frame late or with repeated and skipped frames.

Why

Extraction samples source frames at mediaStart + k/fps, anchored on the clip's start. The lookup reads slot floor((t - start) * fps) for output time t. When start is off the output grid the two grids are out of phase by the sub-frame remainder, so every slot lands one source frame early in time. A start a hair under a frame made floor flip between neighbours, which gave the repeated and skipped frames.

Fix: before the extraction window is resolved, alignClipStartToFirstOutputFrame moves the clip's start onto its first visible output frame and advances mediaStart by the same source time (rate lanes shifted like rebaseVideoToWindow does). Extraction and lookup share that one origin.

Testing

fails without the fix: a clip whose data-start is off the frame grid renders a 30 fps clip where frame N is a gray of 3N and reads what output frames 61 to 65 show.
Without the fix: expected [ 60, 61, 62, 63, 64 ] to deeply equal [ 61, 62, 63, 64, 65 ] for 1.95, 1.9667, 2.0001 and 2.0167, and expected [ 60, 62, 62, 63, 65 ] for 1.999999 (the issue's table).
With the fix: videoFrameExtractor.test.ts 223 passed, three runs in a row.

What I measured

  • The new test red without the fix and green with it, on a Linux devbox with ffmpeg; tsc --noEmit in packages/engine clean; oxfmt applied.

Looped clips are left alone: moving their start would move the loop origin and shorten every cycle, so a looped clip keeps its loop origin when the start is off the frame grid pins that a loop shows the same source frame after every wrap (fails with the shift applied: expected 3 to be 1).

What I did NOT execute

  • A full hyperframes render of the issue's 1080x1920 project, the producer regression suite, and the Windows and macOS lanes.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 116 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • seqplainkeys-none-center-r0-nested-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 0 important · 1 nit · head f5c30900

The non-loop fix holds up, but the start shift makes looped clips drift by a growing amount each cycle (↓ inline, with a repro).

  • nit: the body calls the helper alignClipToFrameGrid; in the code it's alignClipStartToFirstOutputFrame.
Checked
  • videoFrameExtractor.test.ts passes at head (223 tests). The fails-without-the-fix line names the new test and the failure output.
  • Loop repro: a throwaway test next to the new describe (gray = 1.4·N source, extractAllVideoFrames + createFrameLookupTable, timelineEnd: 20), run with the PR's videoFrameExtractor.ts and then with main's.
  • CI is green on this head.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE — 1 resolved, 0 open, 0 new · f5c3090 → 8364534

CI note

The required Tests on windows-latest check is red on this head: engine-cli ran past its 16-minute deadline. The engine tests all passed (2621); it timed out partway through the CLI suite, with no test failure. The same timeout hit main itself at c5a5203 and the merge-queue run for #6772, so this PR didn't cause it. Merging still needs that check to go green. Everything else is green, including Flake gate, on this head. Locally, videoFrameExtractor.test.ts gives 222 passed, and the loop test fails with the shift put back.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 30, 2026
# Conflicts:
#	packages/engine/src/services/videoFrameExtractor.test.ts

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE — 0 open, 0 new · 8364534 → 8151ebc (main merged in; the PR patch against main is byte-identical to the one approved at 8364534)

Checked

Every CI run on this head is green, including the required Windows lanes that timed out at 8364534. Locally the PR's off-grid and loop tests pass. The only local failure is #6772's rotated-clip SAR test, which fails the same way on main with the sandbox's ffmpeg 5.1 and passes in CI.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 10a4ed5 Oct 30, 2026
90 checks passed
@miguel-heygen
miguel-heygen deleted the fix/video-offgrid-start branch October 30, 2026 09:15
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: a <video> clip whose data-start is off the frame grid shows its media one frame late, or stutters when it is a hair before a frame

1 participant