Skip to content

feat(core): a heavy clip's lighter copy can be made ahead of time - #6982

Merged
miguel-heygen merged 4 commits into
mainfrom
feat/preview-light-copy-ahead
Nov 2, 2026
Merged

miguel-heygen merged 4 commits into
mainfrom
feat/preview-light-copy-ahead

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What changes for people

Nothing yet, until a host turns this on. A host can send a new set-copies-ahead control message; while it's on, the preview makes the 1/2-size lighter copy of a heavy clip on screen before it's needed. If the clip then starves, the switch takes about a second instead of waiting for the copy to be made.

  • It's off by default, so Studio and other hosts behave as before.
  • It makes one copy at a time and starts none while the film plays. The host turns it off for anything else that should go first, such as an export.
  • Only clips that isHeavyForPreview calls heavy at the 1/2 size, the same rule and the same cached copy as a real step down.
  • Encodes run at the lowest OS priority until a viewer asks for that copy. The header value X-HF-Proxy-Priority: 0 marks them; a piece already encoding stays low, later pieces run normally. On Unix a process can't raise its own priority back.

fails without the fix: mediaProxy.test.ts, "asks for the copy the first step down would use, and leaves the video on its source", "starts nothing while the film plays", "makes one at a time", "waits for the clip to be on screen"; proxyTranscoder.test.ts, "runs a background copy's encode at the lowest priority, until a viewer asks for it".

What I measured

A real Mac (M-series, 24 GB) running a released desktop build with only this runtime swapped in, 60 s 4K 10-bit HEVC at 80 Mbps, network throttled to 3 MB/s, one run each.

Time to make the copy, small preview (256 px box) 19 s
Time to make the copy, 1024x724 box 25 s
CPU while making it about 1,100 to 1,250% of one core
Disk per minute of footage 3.2 MB (256 px box), 38 MB (1024x724 box)
Copy already made, film at Full, then it starves 4.4 s of hold, then 11.6 s of clean play
Copy already made, film already at 1/2 1.3 s to start after a seek, then 14.7 s of clean play

The CPU row is at normal priority: the server in that build isn't patched, so the low priority is covered by the unit test only.

What I did NOT exercise

  • The low OS priority on a real machine, and whether playback suffers while a copy is being made. A copy already running keeps running during play; only new starts wait.
  • Windows, where the niceness maps to a priority class.
  • Play from the start of a real second open. The 1.3 s above is a Play right after a seek to an unbuffered point, through the throttle.
  • A window resized after the copy was made: the copy is tied to its size, so a much bigger window makes a new one.

Size

9 files, about 190 lines, most of them tests.

@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 · 1 nit · head 31d41538

  • nit: the two new helpers went in between an existing doc comment and the function it describes. copyVariant (packages/core/src/runtime/mediaProxy.ts:506) now sits under swapToProxy's doc block, and lowerPriorityUnlessExited (packages/studio-server/src/helpers/proxyTranscoder.ts:790) sits under spawnFfmpeg's, so the IDE hover text on all four functions is wrong. Moving each helper above its doc block fixes it.
Scope

Read the full diff (9 files). The ahead-of-time URL matches what makeCopy builds for a real 1/2 step-down (same currentSrcValue, variant, scalePreviewProxyBox(shown, 0.5), light=true), so both share one cache entry. One background copy runs at a time and polling stops while the film plays; the server job keeps running because it has no signal, as the body says. The niceness is checked again for each piece and lifted by prioritize. The flag is off by default. Locally, mediaProxy.test.ts passed 72/72 and proxyTranscoder.test.ts passed 76/76. I put mediaProxy.ts, proxyWait.ts and proxyTranscoder.ts back to their main versions: "asks for the copy…", "makes one at a time" and the lowest-priority test then fail. "starts nothing while the film plays" and "waits for the clip to be on screen" are negative tests that still pass against a no-op stub. At 3da5e59a the non-required Comments ratchet failed; 31d41538 fixes it. The required checks were still running when I posted this.

— genesis-v2 (Lane B)

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 111 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-px-r0-nested-z100: tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@miguel-heygen
miguel-heygen force-pushed the feat/preview-light-copy-ahead branch from 31d4153 to ae840b4 Compare November 2, 2026 05:19

@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 new · 31d41538 → ae840b4b. This head is a rebase. The PR diff against the new merge-base matches 31d41538 line for line; only the hunk offsets moved. The base changes to mediaProxy.ts (dropUnneededCopy and the wanted() guard) do not touch the new code. Locally, mediaProxy.test.ts passed 73/73 and proxyTranscoder.test.ts passed 76/76. The earlier doc-comment nit still applies.

@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 new · ae840b4b → aef2a6ad. The only change moves the box choice in nextCopyAhead into copyAheadBox, and it behaves the same. When displayScale === null, every element now gets a null box, so the result is still null. isShown is still called only when the source facts exist. Locally, mediaProxy.test.ts passed 73/73.

@miguel-heygen
miguel-heygen force-pushed the feat/preview-light-copy-ahead branch from aef2a6a to a8a3129 Compare November 2, 2026 06:29

@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 new · aef2a6ad → a8a31295. This head is a rebase. The PR diff against the new merge-base matches aef2a6ad line for line. The 21 base files that changed include none of the files this PR touches, and none of them reference waitForServedProxy, resolveProxy, the priority header or set-copies-ahead. Locally, mediaProxy.test.ts passed 73/73 and proxyTranscoder.test.ts passed 76/76.

@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 new · a8a31295 → 9d728674. The route now passes { background: true } when the header is "0" and { priority: asked === "1" } otherwise, so non-background requests get the same options shape as before this PR, and resolveProxy reads a missing flag as false. Locally, preview.test.ts passed 145/145 and proxyTranscoder.test.ts passed 76/76. The new route test fails against the a8a31295 route.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit e5b10f8 Nov 2, 2026
97 checks passed
@miguel-heygen
miguel-heygen deleted the feat/preview-light-copy-ahead branch November 2, 2026 07:30
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