Skip to content

fix(core): preview fetches only the clips due next, and drops passed clips still downloading - #6160

Merged
miguel-heygen merged 2 commits into
mainfrom
fix/preview-preloads-only-due-and-next-clips
Oct 24, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
fix/preview-preloads-only-due-and-next-clips

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What

Studio's preview now keeps fetches to the clips that matter in a fast-cut film: the clip on screen, the next one on its track, and a few more that are due soonest. A clip the playhead has passed stops downloading while it plays.

Why

A cut sequence with dozens of short clips has most of them inside the 2 s look-ahead. Every one started a full fetch, and the clips already played kept downloading for 4 s more. With about 16 fetches in flight against the browser's 6 per origin, the clip that was due queued behind clips that were not, so later clips entered at readyState 1 and showed a stale frame.

Both are decided in one place, preloadNearPlayhead in init.ts:

  • Upcoming clips take one of 3 slots, earliest first. A clip that is on screen or armed as next on its track never waits for a slot. A slot frees when its clip is playable, or errors.
  • While playing, a clip that has passed and is still loading is released and stays released until the play stops or seeks, except a clip due at the loop start; one that finished loading stays loaded for a scrub back.

Measured

Headless Studio on a synthetic project: 36 clips of 0.2 to 0.6 s, cut from 6 portrait sources (20 MB each) across 4 sub-compositions, played from 0 for 14 s with the link limited to 12 Mbit/s. Clips that entered their window below readyState 3, and clips whose first frame took over 150 ms:

link before after
12 Mbit/s (7 runs) 25 / 24 0 to 9 / 0 (one run: 8)
6 Mbit/s (3 runs) 30 / 30 28 / 2-5
40 Mbit/s 0 / 0 0 / 0

At 12 Mbit/s, before: 24 clips never became ready inside their window. After: 6 of 7 runs had every clip ready on entry or within 141 ms; one run (the machine was loaded) had 8 late. Fetches in flight at once, peak: 16 before, 6 to 9 after.

Before

Frame at 5.4 s on the 12 Mbit/s link. The burned-in timecode of the source shows the clip sitting on its first frame (00:00:00.000).

Before

After

Same moment after the change. The clip shows the frame it should (00:00:06.133).

After

Test plan

  • entry.test.ts: slots hand out earliest first and refill on canplay/suspend/error; a passed clip still loading is released while playing and a finished one is kept. Both fail on main's init.ts and pass here (37 tests in the file; core media, init and entry suites pass).
  • Before/after numbers above, from the same project on the same machine, built from this branch and from main.

Not changed: a render still loads every clip; the capture page and thumbnails use the same code path as the live preview and gain the same limit.

…clips still downloading

A fast-cut film started a fetch per clip inside the look-ahead and let passed clips finish.

@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 · 0 nits · head fd125580

The slot queue itself works: it hands out slots earliest first and refills them as clips settle. The blocker is how spent interacts with the 2 s look-back window. Details are in the inline comment.

Scope

I read init.ts (preloadNearPlayhead, slot helpers, dueSoon, mediaStaysDue, unchangedSincePlayedFrom) and preloadMedia.ts. The 37 tests in entry.test.ts pass locally. I reproduced the blocker with a throwaway probe in the same suite: a networkState getter that load() drives, two clips on one track, and play with keepPlaying steps from 2.05 s to 4.0 s. CI was still running at the time of review.

Comment thread packages/core/src/runtime/init.ts Resolved
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 139 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-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, 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

It was refetched each pass inside the look-back window.

@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 · fd125580 → 1d5978cb

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 23, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 23, 2026
@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit 1790989 Oct 24, 2026
113 of 114 checks passed
@miguel-heygen
miguel-heygen deleted the fix/preview-preloads-only-due-and-next-clips branch October 24, 2026 00:57
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