Skip to content

fix(core): a smaller preview copy nobody wants any more no longer swaps in - #6973

Merged
miguel-heygen merged 2 commits into
mainfrom
dp2/stale-copy
Nov 2, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
dp2/stale-copy

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Design: none (no visible change; a video no longer reloads for a copy nobody wants)

What

When a smaller preview copy is still being made and the preview no longer needs it, the copy is dropped. Before, it swapped in once it was ready, and the video swapped straight back to the right copy.

Why

Lowering the preview level asks for a smaller copy, which can take many seconds. If the level goes back up meanwhile, keepSized saw that the current copy fits and returned, leaving the older ask alive. When that copy was served, the playing video reloaded onto it, then reloaded again to grow back. That is two reloads of a playing video, and its sound, for nothing.

How to reproduce: a video the browser needs a copy for, playing while the level drops to 1/2 and returns to Full before the smaller copy is ready.

How

keepSized drops the pending ask when the current copy fits, which stops its wait (wanted() turns false) and marks the copy ready. Late progress from a dropped ask is ignored.

Size

About 10 changed lines of code and one test. It stands alone: nothing else open touches this path.

What I measured

Desktop app on a Linux rig, no GPU, a generated 120 s HEVC 10-bit clip, 113 s of play. Only the preview runtime differs between the two runs (parent commit and the fix commit, served into the same app build). Both press Use Full while the smaller copy is still being made, and every src and load() on the video is logged:

  • Before: Use Full at film 24 s, the unwanted 256x256 copy swaps in at 70 s, and 304x512 swaps back 51 ms later.
  • After: Use Full at film 33 s, and no swap to the end of the run.

Before: 7 freezes / After: 0 (picture freezes of 120-160 ms in the 10 s clips below). Over film 40-80 s of the whole recordings it is 15 against 0. Most of those come before the 70 s swap, so the swap does not explain them; they fall while the unwanted copy is being made, but I did not establish the cause. Both runs also freeze around 20-40 s, when the first copy lands. In the sound, one tick lands about 70 ms early at the swap in Before; After has none. There is no obvious blink at full speed, so the side by side runs at half speed for the 2 s around the swap, aligned by picture.

The fix commit that ran there differs from this head only by moving a comment into a helper name.
Remote Linux box: mediaProxy 67 tests pass, 3 runs in a row; tsc, oxfmt, oxlint and fallow audit clean. Commit hooks could not run locally, so I ran them there and committed with hooks off.
fails without the fix: drops a smaller copy still being made when the level goes back up, so it never swaps in fails with expected '1024x724' to be '2048x1218' without the keepSized change.

What I did NOT exercise

  • The fix on macOS or on Windows, or with real footage: the app runs above were Linux with a generated clip.
  • The ignored late progress line has no test of its own.
  • Other reloads of a playing video: the first copy landing, and the return to the original when the level goes back up, are unchanged.
before.mp4
after.mp4
side-by-side-half-speed.mp4

@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 blocker · 2 important · 0 nits · head 7827704e

The fix is right: when the current copy fits, keepSized drops the pending ask, so wanted() turns false, the wait loop stops, and the late .then neither loads the copy nor reports it. The fails without the fix: line holds. I reverted only mediaProxy.ts and the new test failed with expected '1024x724' to be '2048x1218'. With the fix, all 67 tests pass, in 2 of 2 runs.

  • important — red Comments check: the new comment at packages/core/src/runtime/mediaProxy.ts:159 raises the file's comment share from 15.2% to 15.3%, so the comment ratchet fails. It is not a required check, but the PR body doesn't mention it. Dropping the comment or folding it into a name turns it green.
  • important — the progress guard at mediaProxy.ts:200 has no test (the PR body says so). Here is what it prevents: a 202 response carrying the progress header is already in flight when the ask is dropped. Without the guard, it writes making after setCopyReportingLevel cleared the map, and copiesReady() stays false. The new test can't catch this because its 202 has no progress header and the drop lands during the Retry-After sleep. One more case would cover it: send the header and delay the fetch.
Scope

I read all of keepSized, requestBox, restoreOriginal, retryPreviewCopies, waitForServedProxy/reportProgress and previewCopies. I checked whether other early returns in keepSized also need to drop the pending ask: lowered && !needed keeps a request that is still needed, and restoreOriginal already deletes it. Required CI was still running at review time.

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 106 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)

@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 blocker · 0 important · 0 nits · 7827704e → 3e075045

The new commit moves the dropped-copy branch into dropUnneededCopy(el) and removes the comment. Behavior is the same as 7827704e, which I approved. The Comments check is green, which resolves that finding. The untested progress guard is unchanged and stays non-blocking. Required CI was still running at review time.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit 6bbda21 Nov 2, 2026
174 of 175 checks passed
@miguel-heygen
miguel-heygen deleted the dp2/stale-copy branch November 2, 2026 04:57
taggedzi pushed a commit to taggedzi/hyperframes that referenced this pull request Nov 2, 2026
Add heygen-com#6973 and heygen-com#6978, which merged ahead of the release PR and shipped in
v0.9.0 without an entry. Correct the PLAN_TOO_LARGE upgrade note: the
plan-size cap only applied to Plan v1, and Plan v2 never raises it.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

1 participant