Skip to content

fix(cli): preserve video frames when scenes reuse element IDs - #6095

Merged
miguel-heygen merged 3 commits into
mainfrom
fix/snapshot-scene-media-identity
Oct 22, 2026
Merged

miguel-heygen merged 3 commits into
mainfrom
fix/snapshot-scene-media-identity

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What

When two scene files each contain <video id="clip">, later snapshot frames can be completely black even though the command succeeds. Give every merged media element a distinct render identity and carry it through snapshot extraction, injection, and visibility.

Why

Inlining makes scene-local IDs ambiguous. Snapshot addressed both videos as clip; injection found the first video, skipped its hidden scene, and left the visible second scene without footage. Authored IDs must stay intact because scene CSS and scripts use them.

This fixes the reproduced scene-identity failure. The separate macOS report where multi-time calls fail but individual calls succeed was not reproduced with the unique-ID synthetic fixture, so this PR does not establish that report's cause.

Related work

Reuses the existing canonical allocator and browser lookup bridge. No transcode-cache behavior changes.

How

  • Allocate render IDs after all scenes are inlined. Preserve unique existing stamps, repair duplicate stamps, and reserve media and audio-bus identities before allocating new ones.
  • Install the existing bridge before capture navigation. Snapshot candidates and frame visibility use the same identity already accepted by injection.
  • Preserve authored element IDs and repaired identities across recompilation.
  • Raise only Core's unpacked size budget by 359 bytes for the shared bundler and allocator code. Other package budgets are unchanged.

Producer/consumer review:

Producer Consumer Result
Combined-document allocator Snapshot candidate collection Unique identity across scene files, including pre-stamped inputs
Candidate ID Frame extraction and injection Passed unchanged; bridge resolves the stamped element
Active frame IDs Visibility synchronization Uses the same identity as injection
Repaired audio-bus IDs Member pairing Pairing runs after allocation and reads final stamps

Independent review checked the complete change and hostile identity/order states, then approved the corrective delta with no remaining findings. Unit tests enter the real bundler and command paths, but mock browser infrastructure; the separate CLI captures exercise real Chromium, decoding, injection, and screenshots.

Test plan

  • Five touched test files each passed alone three times: bundler integration (2), allocator (19), screenshot service (37), snapshot command (77), and browser recovery (8). No skipped tests.
  • Regression witnesses fail when the corresponding implementation changes are removed. Restoring the old allocator fails the pre-stamped integration and both new allocator behaviors.
  • Real CLI fixture: synthetic 304-second, 3840×2160, 60fps HEVC MOV with rotation -180. Two scenes reuse clip. Three runs include forward and backward seeks; all nine images exactly match independent FFmpeg source-frame references.
  • Eight-cut unique-ID control passed at nine requested times and remained pixel-identical after the fix.
  • Real check --snapshots passed with no lint, runtime, layout, motion, or contrast issues. One expected craft warning identifies the silent synthetic fixture.
  • Core, Engine, and CLI typechecks and builds passed. Packed-consumer verification passed Node execution, NodeNext declarations, Vite resolution, CLI startup, and all package-size budgets.

Browser proof is Linux Chromium. Windows recovery is covered by mocked browser tests; this does not establish macOS runtime behavior or an exported video result.

Before

Second scene at 12 seconds, baseline commit 807803a45. Black output despite command success.

Before: second scene at 12 seconds

After

Same synthetic fixture and 1080×1920 viewport at the PR head. Second scene shows the correct frame.

After: second scene at 12 seconds

@mintlify

mintlify Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

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

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 22, 2026, 10:18 PM

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

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

Reviewed exact cde06fd3f58d7eab5f3ed12912fec208687c58da.

Need · Size · Reuse · Simpler: Applying the canonical media allocator after inlining addresses scene-local ID collisions without renaming authored IDs. Capture installs and consumes the existing identity bridge instead of adding another naming scheme.

Audited: allocation/reservation and duplicate repair, bundler placement, scoped audio-bus member pairing, bridge/export/navigation ordering, snapshot candidate IDs, injector/visibility consumers and recompilation behavior. Existing unique stamps are reserved before allocating replacements, including media/bus collisions and future suffixes; repaired stamps remain stable. Idless media receive nonempty identities. Authored IDs and direct-engine fallback lookup remain intact.

Validation: 58 allocator/bundler/screenshot unit and integration tests passed locally (19+2+37). This adapted harness used own-source aliases, borrowed dependencies and a borrowed generated runtime fixture; screenshot/browser infrastructure is mocked. Fresh adversarial source review found no blocker across hostile identity/order states. The 359-byte core budget change is isolated, but package size was not independently rebuilt here.

The authored Linux CLI captures/screenshots remain author evidence. I did not independently run the 304-second fixture, exported video, packaged CLI, Windows recovery or macOS multi-time report. This review does not establish that separate macOS report's cause.

— hf-review

Verdict: APPROVE
Reasoning: Producer and consumers now share document-unique identities across merged scenes, preserving styling IDs and recompile stability. No blocker found.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 152 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)

@jrusso1020 jrusso1020 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-reviewed exact e1908581b179e384d6b1b81af9d9bf82fe2e7125 against my approved cde06fd3f58d7eab5f3ed12912fec208687c58da.

Need · Size · Reuse · Simpler: This successor changes only pageBuild.preview.html and pageBuild.render.html goldens. Each adds document-unique data-hf-render-id="hf-media-0/1/2" to the three repeated idless images, matching the existing allocator's document-order fallback. Removing those six added attributes recovers the approved golden files byte for byte. No implementation, test logic or manifest changed.

Validation: all 19 allocator tests pass at this head using borrowed dependencies. The four page-build golden tests could not run successfully in this local dependency setup: parser subpath resolution, then missing entities/decode, blocked execution. I verified the complete golden delta directly; I am not reporting those tests as passing.

My earlier producer/consumer, allocation/pairing and snapshot integration review remains applicable to the identical source. Its 58 adapted tests are prior-head evidence, not a fresh full-suite run. No new independent real CLI capture, exported video, package-budget rebuild, Windows or macOS acceptance was performed.

— hf-review

Verdict: APPROVE
Reasoning: The golden-only successor records the already-reviewed distinct media identities without changing source behavior or unrelated expected output.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit da6b77b Oct 22, 2026
84 checks passed
@miguel-heygen
miguel-heygen deleted the fix/snapshot-scene-media-identity branch October 22, 2026 23:48
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