Skip to content

fix(studio): Studio shows a video's own file, not its preview copy, and copies only on request - #5801

Merged
miguel-heygen merged 3 commits into
perf/seek-proxiesfrom
perf/authored-src-not-copy
Oct 18, 2026
Merged

miguel-heygen merged 3 commits into
perf/seek-proxiesfrom
perf/authored-src-not-copy

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What changes for the user

A copy no longer leaks into Studio. Studio keeps seeing the video's own file after a copy swaps in. Before, it saw a new source: it fetched the copy, ran its beat analysis on it again (about 2.5 s on the main thread) and regenerated its thumbnails. That froze the page for 3 s and stalled it several times over the next 15 s.

Copies only when the page asks. Opening a project no longer encodes copies on a guess. A copy is made only when the page's own canPlayType says it cannot play the file, or for the background seek copies the page itself asks for.

Copies only when the page asks. Opening a project no longer encodes copies on a guess. A copy is made only when the page's own canPlayType says it cannot play the file, or for the background seek copies the page itself asks for.

On macOS, Electron decodes 10-bit HEVC itself, yet the server pre-encoded a full H.264 copy of it at project open (229 MB, encoding through the first 100 s of playback). It now encodes only when the page asks.

Before and After

A 10-bit HEVC clip from the repo's HLG test fixture, opened in Studio in headless Chromium on Linux, which cannot decode it, so the preview plays a copy. The property panel's source field:

Before

Before: the property panel's source field shows the preview copy's address

The field shows the copy's address. Remove BG is greyed out, because the panel cannot find the file in the project.

After

After: the property panel's source field shows the video's own file

The field shows the video's own file, and Remove BG is available again.

The panel normally cuts long paths short; in both captures the source text is set to wrap so the whole value shows.

What it does

The authored source stays the only source Studio sees (runtime and Studio)

  • unproxiedSrc (core/src/runtime/proxySrc.ts) is the one owner of "this element's authored src". The runtime's clip list (timeline.ts) and element picker (picker.ts) read through it.
  • The runtime exposes it to Studio as window.__hf.unproxiedSrc. Studio reads it through one helper, authoredSrc (studio/src/utils/authoredSrc.ts), which every Studio reader of a preview media src now uses: the clip-list builders, the property panel's source fields, color grading, the audio fx readers and copied markup.
  • The swap's src write is now the runtime's own write (withoutOwnTimingRecords), so it no longer bumps the composition timing revision. That bump rebuilt the media index and re-posted the clip list.
  • Right after the write, one exact media sync puts the new file on the playhead, including while paused. Before, a copy swapped in while paused showed its first frame until the next seek or play.

No guessing whether a copy is needed (studio-server and CLI)

  • Serving a page no longer pre-encodes copies. The pre-warm path (shouldPrewarmProxy, the prewarm flags in BROWSER_HOSTILE_CODECS, injectMediaCodecMapIntoHtml's pre-warm loop) is removed. So is its demand telemetry (recordProxyPrewarm, recordProxyRequest, mediaProxyDemand), which only measured how often a pre-warm was used.
  • The CLI's static project server and hyperframes play reached that path; Studio's preview never did.
  • Kept, because they are explicit outputs rather than guesses:
    • publish bakes copies into the published bundle so it plays in any browser;
    • check makes copies so it can warn when one cannot be made.
  • The light ./player entry stays free of the parsers: authoredSrc lives in its own module.

Tests

Each new test was checked against its change: with the change reverted, the test fails; with it restored, it passes. Every touched suite passed 3 runs in a row.

  • runtime/mediaProxy.test.ts, picker.test.ts, init.seekCopies.test.ts: after a copy swaps in, the clip list, the picker and window.__hf.unproxiedSrc still give the authored src.
  • runtime/init.mediaClipIndex.test.ts: the swap's write leaves the media index alone and puts the copy on the playhead while paused.
  • studio/src/utils/authoredSource.test.ts, studio/src/player/lib/timelineElementHelpers.test.ts: Studio's clip list and copied markup use the authored src.
  • mediaProxyPreview.test.ts: serving a page whose codec map has HEVC, ProRes and VP9 entries starts no copy. The existing ?hf-proxy= request tests (routes/preview.test.ts "serves proxy bytes with Accept-Ranges...", CLI staticProjectServer.test.ts "serves the resolved proxy's bytes...") show a page's request does.
  • studio/src/lightEntries.test.ts (existing): the ./player entry loads without the parsers.

Stack

Stacked on #5799 (one copy per video), which is stacked on #5769.

@miguel-heygen
miguel-heygen force-pushed the perf/one-copy-per-video branch from 1cc3906 to 3b11e80 Compare October 17, 2026 15:06
@miguel-heygen
miguel-heygen force-pushed the perf/authored-src-not-copy branch 3 times, most recently from 0dc0192 to 4c21a79 Compare October 17, 2026 16:49
@miguel-heygen
miguel-heygen force-pushed the perf/one-copy-per-video branch from d818616 to 13efb25 Compare October 17, 2026 17:02
@miguel-heygen
miguel-heygen force-pushed the perf/authored-src-not-copy branch from 4c21a79 to 1470f56 Compare October 17, 2026 17:11
…only when the page asks

Studio and the clip list read a video's authored src, never the copy it plays. The server no longer pre-encodes on a codec guess; a copy starts only from the page's request.
@miguel-heygen
miguel-heygen force-pushed the perf/one-copy-per-video branch from 13efb25 to ba43a5c Compare October 17, 2026 17:45
@miguel-heygen
miguel-heygen force-pushed the perf/authored-src-not-copy branch from 1470f56 to 44e0b14 Compare October 17, 2026 17:45
@miguel-heygen miguel-heygen reopened this Oct 18, 2026
Base automatically changed from perf/one-copy-per-video to perf/seek-proxies October 18, 2026 00:54
@miguel-heygen
miguel-heygen merged commit 44e0b14 into perf/seek-proxies Oct 18, 2026
49 of 53 checks passed
@miguel-heygen
miguel-heygen deleted the perf/authored-src-not-copy branch October 18, 2026 00:54
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