Skip to content

fix(core): retain complete preview pictures during native seeks - #7378

Merged
jrusso1020 merged 2 commits into
mainfrom
fix/native-preview-seek-coherence
Nov 7, 2026
Merged

jrusso1020 merged 2 commits into
mainfrom
fix/native-preview-seek-coherence

Conversation

@jrusso1020

Copy link
Copy Markdown
Collaborator

What

A paused seek across stacked video cuts keeps the previous complete video and HTML picture visible until all destination layers have decoded. This prevents captions over black and a transparent person layer appearing without its background.

Why

The composition clock and clip visibility previously advanced before independent native media seeks finished. Moving across cuts could also release and reopen sources, making those incomplete pictures visible.

Related work

First of two smaller PRs replacing the combined scope in #7346. The follow-up branch fix/full-quality-webcodecs-scrubbing targets this branch and adds the optional decoded-frame provider and Studio integration. This PR is independently usable and does not install WebCodecs or activate the provider. Merge this PR first; then retarget/rebase the follow-up onto main.

How

  • Hold native video snapshots and retain graded output while destination scenes and media become ready; commit video visibility and composition timing together.
  • Serialize seeks and coalesce queued input to the newest destination. Scene changes and source reloads refresh readiness.
  • Release retained pictures on Play, render seek, stop-media and teardown. Preserve leased/host-controlled media and bound stalls with wall-clock timers.

Test plan

  • Regression fails against current main: a seek to 5.5 advances the composition immediately instead of retaining the old picture. The same test passes with this change.
  • Full repository build.
  • Four focused runtime suites: 362 tests passed.
  • Runtime CI suite: 2,881 tests passed, plus contract, behavior, seek, parity, security and linter scripts.
  • Commit hooks: lint, formatting, type checks, Fallow, tracked artifacts and commit message checks passed.
  • Chromium 156 browser reproduction against this built branch using generated opaque and alpha video. At the requested 6.367-second jump, the video and HTML clocks retain the complete 0.467-second picture until both destination layers are ready; subsequent jumps land with both layers ready. No page errors.
  • Player documentation updated.

This addresses native DOM/graded-video seek presentation. The optional provider and graphics-consumer compatibility belong to the follow-up. No merge, release, Canary bundle change or private project upload is part of this PR.

Before

Original seek behavior on the same generated test-pattern and alpha-circle composition: HTML reaches 6.367 seconds while media layers are blank. This reference capture is from the original baseline used for the investigation; the unit regression above was separately reproduced against current main.

Original seek exposes incomplete video layers

After

Fresh capture from this PR on current main: the requested timeline is at 6.367 seconds while video and HTML both retain the complete 0.467-second picture during decoding.

Native seek retains a complete picture

All capture media is synthetic. No user footage, images or voice are included.

@mintlify

mintlify Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

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

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Nov 7, 2026, 8:52 PM

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

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

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

  • seqplainkeys-none-pct-r0-nested-z100: tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true
  • seqab-none-pct-r0-root-z100: tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review at 9d5b242: looks good to merge on its own. CI is green (89 pass, 11 skipped).

Paused seeks hold every visible native video as a snapshot and keep timeline, captions and scenes at the old time. Everything commits together once each video is readyState ≥ 2, not seeking, and within 0.02 s. That tolerance matches syncRuntimeMedia's forceSync threshold, so it can't get stuck on a mismatch. Rapid seeks coalesce. Play, renderSeek, onStopMedia and teardown all cancel.

Non-blocking:

  • previewSeek.ts:8,136: at the 5 s cap it commits the mismatched picture anyway after a 5 s freeze. That's a fine fallback, but long next to the 1 s image-hold cap.
  • holdVideoFrame inserts the snapshot as the video's previous sibling with copied styles, which can briefly shift video + x / :first-child selectors. Low risk.
  • colorGrading.ts drawableFrame returning null during the hold freezes graded layers too. That's coherent.

@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 · 2 important · 0 nits · head 9d5b242c

Adds to @miguel-heygen's review, which already covers the 5 s cap fallback and the sibling-selector shift. These are the gaps it doesn't mention.

  • Merge order (UX): on its own, this PR never commits an intermediate picture while the user is dragging. finish() re-runs for the newest destination and doesn't publish, so the picture stays frozen for the whole drag (the 0.700 s still in #7379's Before capture). Ship it together with #7379, or port #7379's "publish the intermediate if it's ready" branch into this PR.
Scope

Read previewSeek.ts and the init.ts changes end to end. CI is green on this head. Local core runtime suite: 2881/2881 passed. Findings 1–2 were confirmed with scratch vitest repros (not committed).

— HyperFrames Team Review Agent (Genesis)

Comment thread packages/core/src/runtime/init.ts Resolved

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction to my earlier note: I no longer think this is ready to merge alone. ready() in previewSeek.ts:75-85 treats an element as done only if it is disconnected, el.error != null, or readyState ≥ 2 at the target. A video whose sources never load (for example, a missing <source> with no src) sits at NETWORK_NO_SOURCE with error === null and readyState 0. So every paused seek waits for the 5 s cap, where main lands immediately. It should also count networkState === NETWORK_NO_SOURCE (and perhaps NETWORK_EMPTY) as done, plus add a test.

@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 — 3 resolved, 0 open, 0 new · 9d5b242c → 4ffd6759. CI is green on this head. The approval covers this SHA only.

— HyperFrames Team Review Agent (Genesis)

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review at 4ffd675: looks good to merge. Each claimed fix is confirmed by a test that fails when the change is reverted:

  • failed sources settle (isUnplayable covers NO_SOURCE, and the capture-phase error listener catches <source> errors)
  • newer clip selections supersede stuck work
  • complete intermediate pictures publish
  • image waits keep the hold

CI is green (89 pass, 11 skipped).

Non-blocking:

  • A newer seek within the same clips still waits for the stuck run's cap.
  • No test covers canplay.
  • The cap still commits a mismatched picture after 5 s.

@jrusso1020
jrusso1020 added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit b87a01f Nov 7, 2026
100 checks passed
@jrusso1020
jrusso1020 deleted the fix/native-preview-seek-coherence branch November 7, 2026 23:45
@miguel-heygen miguel-heygen mentioned this pull request Nov 8, 2026
3 of 5 tasks
SanHsien added a commit to SanHsien/hyperframes that referenced this pull request Nov 9, 2026
Port the adopted upstream fixes from f5bde95 to the current upstream tip:
heygen-com#7375 multipart cloud upload, heygen-com#7382 minParallelChunks, heygen-com#7349 HLG header SEI,
heygen-com#7369 skip unmounted compositions in lint/check, heygen-com#7381 filesystem-path media
in the cloud archive, heygen-com#7383 Safari cut-point pre-roll revert, heygen-com#7373 clock
steering between audio time updates, heygen-com#7384 injector test isolation, heygen-com#7378
preview seek retention, heygen-com#7390 virtual timer schedule per worker, heygen-com#7394 CDN
script failure naming, heygen-com#7395 menu row radius, heygen-com#7119 decode timeout caller
test, heygen-com#7397 authored tween order, heygen-com#7402 capture page clip loading, heygen-com#7412 muted
video audio track at cuts, heygen-com#6150 template root variable test, heygen-com#7442 held tail
seek once.

Deliberate local differences: heygen-com#7067's audio-start hold is not carried into
clock.ts, mountedSources comes from heygen-com#6827 as a helper only, cloud/_gen/types.ts
omits the image-request types the fork does not generate, and the lint
symlink test skips through symlinkOrSkip where the account cannot create links.

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
SanHsien added a commit to SanHsien/hyperframes that referenced this pull request Nov 9, 2026
The 1a9bb89 port of heygen-com#7402 and heygen-com#7378 brought in releaseMedia(el, flag)
with window.__HF_RELEASE_PASSED_MEDIA (heygen-com#6929, needs the heygen-com#6785 buffered
guard) and registerSeekCompletion(landed, "image-decode") (the SeekHold
union from heygen-com#6596). Both upstream commits stay deferred, so typecheck:runtime
failed in the Windows render verification workflow. The fork's
releaseMedia already frees every clip, so the call keeps its behaviour.

Add tsconfig.runtime.json to the pre-commit typecheck, which only covered
tsconfig.json (it excludes src/runtime), and pin it in the hook test.

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
julienhmmt pushed a commit to julienhmmt/fork-hyperframes that referenced this pull request Nov 9, 2026
* fix(skills): await the player seek in seam-gate

heygen-com#7378 made __player.seek() asynchronous (it resolves once the preview
picture is ready). seam-gate.mjs seeked and read in the same tick, so
every sample measured t=0: on a correct film each seam failed with
exit-visible op 0.00 and exit-moving 0 px/s, and probe found no movers.

Make the page-side seek/sample/scan helpers async and evaluate them with
awaitPromise, and note the false-failure signature in the reference doc.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs(skills): await the player seek in changelog-video spot checks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

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

This branch was successfully deployed

1 active deployment
staging - docs — 4ffd6759 Deployed Nov 7, 2026 by mintlify[bot]
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.

2 participants