Repository navigation
fix(core): an element its script hides stays hidden while studio preview plays - #5458
Merged
Merged
Conversation
Contributor
Edit accuracy: accurate 2061 (base branch 2061), smooth 1607 of thoseThe gate passes. Quarantined, measured but not gated (0) |
…ts new window Studio timing edits drop the runtime-stamped mark, and a script-hidden stamped container no longer holds back its images.
…es the render Only the Studio preview honours the stamp, copied live markup drops it, and a lane-only move makes a stamped element authored like the save does.
jrusso1020
approved these changes
Oct 11, 2026
jrusso1020
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed at c7fa1fec. Approving, no blockers.
The fix is at the right layer. Stamped elements get a full-length window only so the timeline can list them, so the per-tick visibility pass has no timing of its own to enforce on them and now leaves visibility to the author. The stamp name moves into studioPreviewMark.ts as one constant, and there's one helper (applyAuthoredTiming) for "this element's timing is now authored". That reuses the existing preview-mark module instead of adding a new one.
Checked against the PR body
- "Studio's copy now strips it": the strip comes from adding the stamp to
PREVIEW_ONLY_ATTRS. That coversliveMarkupWithoutPreviewMarks(authoredSource.ts:102) and the layer-copy deny list (domEditingLayers.ts:59), so no change toauthoredSource.tswas needed. - "Studio's one timing write onto the preview": every live timing write goes through
patchIframeDomTiming. That'suseTimelineClipTimingEditing.ts:134, 255anduseTimelineGroupEditing.ts:250, 387, so moves, trims, lane changes and media-offset edits all drop the stamp. - Renders are unchanged: the skip is gated on
stampsForStudio(window.parent !== window), the same condition the stamping pass already used. - One side effect, and it's correct:
init.ts:297buildsRUNTIME_MEDIA_ATTRSfromPREVIEW_ONLY_ATTRS, so a stamp on a<video>/<audio>is now ignored when comparing a media element's written shape. It's a runtime write, so it belongs in that set.
Run at this head
- core
init.test.ts: 233 pass. studiotimelineEditingHelpersandauthoredSource: 27 pass. - Mutants:
- Forcing
isRuntimeStamped = false(reverting the fix) fails a test. - Dropping the
stampsForStudioguard fails the render test.
- Forcing
— Rames
lovicho
pushed a commit
to lovicho/hyperframes
that referenced
this pull request
Oct 11, 2026
…hile the preview plays (heygen-com#5475) A 9:16 fixture with a looping A-roll video, an untimed full-frame backdrop above it that the film's own GSAP script shows only from 6 s to 8 s, captions on top and two sub-compositions. The check plays it in Studio's preview and reads the preview's pixels and the element on top at the frame's centre: the video must show at rest and while playing outside the backdrop's window, and the backdrop must show inside it. It fails with heygen-com#5458's visibility skip reverted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes for a user
In Studio preview, a video no longer goes black while playing when the composition's own script hides a layer above it. Before, a full-frame backdrop that a script kept hidden was forced visible on every playing tick, so a talking-head under it showed only when paused (captions above the backdrop kept playing). Rendered video was never affected.
Before
After
Why
In Studio preview only, the runtime gives every untimed element with an id under the root a full-length timing, marked
data-hf-autostamped, so the timeline can list it (init.ts, the stamping pass inbindCapturedTimeline).applyTimedElementVisibilitythen wrotestyle.visibilityon every timed element on every tick, including those stamped ones, so it overwrote an author'svisibility: hidden. While playing, that pass runs after the composition's own per-frame update, so "visible" won; on pause the composition's update ran last, so the layer hid again.Stamped elements have no authored timing of their own, so the pass now leaves their
visibilityto the author. Hide-layer (data-hidden) handling and authored timed clips are unchanged, and an in-flow stamped element still collapses withdisplay:noneoutside its window, as before. Clip layout already skips stamped elements for the same reason.The stamp only counts in Studio preview: a stamp that ends up in a project file (copying a live element) no longer changes a clip's visibility in a render, and Studio's copy now strips it. In a render such a stamp still keeps the element in page flow, as before this change. Once a person moves, trims or re-lanes a stamped element in Studio's timeline, its timing is authored, so it must hide outside its new window like any clip. The mark's name and a helper that writes authored timing and drops the mark now live in core (
studioPreviewMark.ts:RUNTIME_STAMPED_ATTR,applyAuthoredTiming), and Studio's one timing write onto the preview (patchIframeDomTiming) goes through it. The preview's hidden-image skip also leaves stamped elements alone, so images inside a container its script hides are still fetched ahead and a paused seek does not wait on them.Renders never stamp (they run as the top-level page), so export output is unchanged.
Checked
init.test.ts: a stamped element re-timed through the same helper and rebind Studio uses hides outside its new window (hidden / visible / hidden at 1 s, 5 s, 8 s; fails without the mark removal); a paused seek does not wait on images in a stamped container its script hides (fails without the selector change).timelineEditingHelpers.test.ts: editing a stamped element's timing makes it authored; a lane-only move makes it authored too.init.test.ts: a render times a clip by its window even when its source carries the stamp.authoredSource.test.ts: copied live markup drops the stamp.init.test.tscases: a GSAP per-frame script that hides an untimed backdrop over a video stays hidden across 120 playing ticks (fails without the change, passes three runs in a row); a stamped element its author never hides still shows; an authored clip inside a hidden authored clip under a stamped wrapper stays hidden.src/playerandsrc/hooks: 3859 tests pass. oxlint, oxfmt, comment ratchet clean. Generated runtime bundles are unchanged by the build.Not covered here
Re-timing an untimed top-level element in the timeline now takes it out of the page's normal layout flow straight away (as the render places it), not only after a reload.
A paused seek no longer waits for images inside a stamped container its script hides, so one frame can paint before they load.
Not run on macOS or in other browsers.
Other Studio suites and the CLI/engine suites were not run.