Skip to content

fix(cli): check copies only the stretch of a video it plays and stops after 2 minutes of copies - #7182

Merged
miguel-heygen merged 7 commits into
mainfrom
fix/check-copy-budget
Nov 4, 2026
Merged

miguel-heygen merged 7 commits into
mainfrom
fix/check-copy-budget

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What

hyperframes check makes a browser-playable copy of any video Chrome cannot decode (HEVC, ProRes) before it opens the page. It copied the whole file, outside the check's deadline, ended only by a 3 minute no-progress stall. A long source that kept moving held the check for 8+ minutes with no result, which agents read as a hang.

Two changes:

  1. Copy only what the composition plays. When every use of a file is a <video> with a known data-duration (on the video or the element that times it, no loop), check copies only that stretch from the start (plus offset, rate rounded up, rounded to whole 15 s pieces). Anything else still copies whole and shares the preview's copy. The window is part of the copy's cache key, and the check's local server serves the same windowed copy when the page asks for the video, so the page never starts a second full copy. The finding crop and frame capture pages get the same windows, computed from the same page HTML. A window is used only when it saves at least one piece.
  2. A backstop. The inline copy has a 2 minute budget. Past it, check stops with a media_copies_unfinished finding naming each unfinished file with its progress and hyperframes check --prepare-media (no time limit); finished pieces are kept, so the next run continues.

Studio preview and the other callers are unchanged: they pass no window and get the whole-file copy as before.

Measured

A 90 s 4K portrait HEVC clip, composition plays 5 s of it (devbox, 4 cores): copy 6.5 s windowed (one copy in the cache, page requests served from it) against 32.7 s whole when the composition gives no duration.

Fails without the fix: packages/cli/src/utils/checkBrowser.test.ts > "copies only the stretch of a long video the composition plays" and "stops a check whose copies outrun the copy budget, naming each file and the way to finish"; packages/studio-server/src/helpers/proxyTranscoder.test.ts > "copies only the first stretch when asked, as a copy of its own"; checkBrowser.test.ts > "serves the page the same copy windows the check made, so a capture starts no full copy"; packages/cli/src/utils/mediaUsedSeconds.test.ts (new file, 5 cases).

Not covered

The craft-sampling stop and the queue-wait budget from the same reports are separate follow-ups. A video with no known duration (no data-duration anywhere above it) still copies whole.

@mintlify

mintlify Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Nov 4, 2026, 8:21 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 117 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 (8)

Unstable (1)

  • seqplainkeys-none-px-r0-root-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

@miguel-heygen miguel-heygen changed the title fix(cli): check stops after 2 minutes of video copies and says how to finish fix(cli): check copies only the stretch of a video it plays and stops after 2 minutes of copies Nov 4, 2026

@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.

Requesting changes at cd44b0ae. The approach is sound, but the finding-capture page still starts a whole-file copy. That's the copy this PR says check no longer makes.

Blocker 1: crop and frame capture still copy the whole video
runBrowserCheck passes limits to serveStaticProjectHtml, but withFindingCapturePage (checkBrowser.ts:738, used by captureFindingCrops and captureFindingFrames) opens its own server with no proxyLimits. When that page asks for the HEVC/ProRes clip, serveProxyRequest calls resolveProxy with limitSeconds: undefined. That looks up the whole-file cache key, and only the windowed copy exists (h264@30s). So it starts a full transcode.

Before this PR, the pre-resolve step had already made the whole copy, so this page got a cache hit. Now any check that reports findings needing crops or frames, on a project with a long hostile video, starts the full 4K copy in a phase the 2-minute copy budget doesn't cover. The crops and frames also wait on that copy or come out without the video's pixels. This contradicts the body's claim that "the page never starts a second full copy".

Fix: carry the limits from the pre-resolve step, or recompute them, into withFindingCapturePage's serveStaticProjectHtml call. Then add a test that the capture server resolves with the same limitSeconds.

Blocker 2: the Comments workflow is red on this head

RAISED comment share: packages/cli/src/utils/staticProjectServer.ts is 11.1% (44/395), at the base 11.1% (43/388)
RAISED comment share: packages/studio-server/src/helpers/proxyTranscoder.ts is 6.7% (82/1219), at the base 6.7% (79/1177)

Checked, no issue

  • The Fails without the fix: line is present and names specific tests.
  • mediaUsedSeconds covers the runtime's offset and rate attributes (data-media-start, data-playback-start, data-playback-rate). It rounds rate < 1 up to 1 and leaves loop, untimed, non-<video> and <source> uses out of windowing. All of these err toward a longer copy, which is the safe direction.
  • --prepare-media computes the same windows with the same cache key, so its output satisfies the next check.
  • Studio and other callers pass no window and get the whole copy as before.

Nit (non-blocking)
If the budget timer fires just as the last copy settles, overBudget is set but no result is rejected. Check then throws media_copies_unfinished with an empty file list. Only throw when unfinished.length > 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.

Approving at b62be740. Both blockers from my review at cd44b0ae are fixed.

  • Capture pages get the copy windows. withFindingCapturePage now passes copyWindows(project.dir, html, …) to serveStaticProjectHtml. That is the same mediaUsedSeconds + proxyWindowSeconds calculation the pre-resolve step uses, keyed by resolve(projectDir, file) on both sides. So a crop or frame capture hits the windowed cache entry and starts no full copy. The new test "serves the page the same copy windows the check made" pins this down. The extra ffprobe on non-hostile timed videos can't throw, because probeMediaMetadata turns errors into probeError. A missing or remote src just gets no window.
  • Comments gate. It's green on this head.
  • Nit from my last review. Also fixed: the error now needs unfinished.length > 0.
  • Later heads. 5912a32c removes only a comment. b62be740 extracts copiedSeconds and lengthArgs. These keep the old behaviour: range?.lengthSeconds ?? limitSeconds picks the same -t as the old ternary.

CI is green on b62be740, and the cli and studio-server test files touched here all ran. Windows render verification was still running when I approved.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit c6f87f5 Nov 4, 2026
93 of 95 checks passed
@miguel-heygen
miguel-heygen deleted the fix/check-copy-budget branch November 4, 2026 21:33
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