Source: Timeline Editing, Keyframes & Arc Motion, Studio Manual DOM Editing — HeyGen HyperFrames docs
HyperFrames Studio is the last-mile visual editor over HTML-authored compositions. It exposes three editing surfaces — a timeline (move/trim clips), visual keyframe tools (edit GSAP animation without code, including Arc Motion and gesture recording), and a manual DOM inspector (move/resize/style/text elements on canvas). The unifying rule across all three: Studio only exposes interactions it can round-trip back to authored HTML deterministically, persisting to data-* attributes and inline styles rather than a separate project format. Edits stay inspectable and versionable in source.
Key Takeaways
- Source of truth is the HTML. No separate project file or hidden binary state — every supported edit updates
data-*attributes and inline styles your composition already uses. Open the file after an edit and you see exactly which attributes changed. - Timeline = move + trim only. Horizontal drag →
data-start; vertical drag →data-track-index; right-handle drag →data-duration; row order → inlinez-index. Split/slip/slide/ripple/roll semantics are intentionally not implemented yet. - Front-trim is media-only.
video/audio(and wrappers withdata-media-start/data-playback-start) can skip their own content from the start; generic motion clips (div,section, GSAP elements) have no playback-offset model, so the left trim handle is hidden rather than faked. - Keyframes are synthesized from GSAP tweens. Every
.to(),.from(),.fromTo()produces start/end diamond markers; the Design Panel Animation section edits method, timing, ease (with a live speed-curve preview), and per-property values, writing valid GSAP that renders identically in preview and headless export. - Arc Motion turns a flat x/y
.to()tween into a curvedmotionPath(GSAP MotionPathPlugin), with a 0–3.0 Curviness slider (1.5–2.0 recommended) and optional Auto-Rotate. The plugin CDN script is added automatically. - Gesture Recording (press
R) samples pointer drags at ~60fps and simplifies ~180 raw samples into 5–15 clean GSAP keyframes. - Computed timelines stay editable. Helper/loop-generated tweens show an “Unroll to edit” action (visual no-op that rewrites them to literal tweens); truly computed values stay display-only and edit in the Code tab.
- DOM editing is capability-gated. Move needs a stable patch target +
absolute/fixedposition + pixelleft/top+ no transform; resize additionally needs patchable pixelwidth/height. Layout-owned layers get an explicitMake movableinstead of silently converting on drag. - A clipboard / Ask-agent bundle copies structured element context (id, file:line, position, size, tag, animation, properties) to hand spatial context to an AI agent.
Timeline Editing
The Studio timeline edits the parts of a composition that persist cleanly back into source HTML. Five supported actions:
| Action | Gesture | Persists to |
|---|---|---|
| Move clip in time | drag horizontally | data-start |
| Move clip between rows | drag vertically | data-track-index |
| Change visual stacking | reorder rows (top renders above) | inline z-index |
| Trim end of clip | drag right handle | data-duration |
| Trim start of media clip | drag left handle (media-backed only) | data-start + data-media-start or data-playback-start |
Stacking rule: the visually top row renders on top, lower rows underneath. Put captions, lower-thirds, and overlays on a higher row so they sit above base footage.
Editing model by clip type
- Generic motion / DOM clips (
div,section,aside, GSAP-driven cards/overlays/text): can move (earlier/later, between rows) and right-trim (end). Cannot true-front-trim — there’s no way yet to start the internal animation partway through. - Media clips (
video,audio, wrappers backed bydata-media-start/data-playback-start): all of the above plus start-trim of the media content itself.
Why start-trim is media-only
Media clips carry a real content-offset model (data-media-start, data-playback-start) that lets Studio say “start this clip later on the timeline and start reading the media later inside the source.” Generic motion clips have no equivalent playback-offset, so Studio can move the whole clip (data-start) or shorten its window (data-duration) but cannot start the animation halfway. The left trim handle is therefore hidden for motion clips rather than implying behavior the runtime can’t represent truthfully.
Mental model: move changes when a clip starts, right trim changes when it ends, left trim only appears when the clip can actually skip the beginning of its own content.
Current limitations
- No true front-trim for generic motion clips yet.
- Layering is row-order + persisted inline
z-index; custom CSS stacking rules outside the Studio flow can conflict — keep them in mind when editing manually. - Scope is deliberately move + trim; no split, slip, slide, ripple, or roll editing.
Keyframes & Arc Motion
Visual tools to create/edit GSAP keyframes without writing code.
Timeline keyframe diamonds
- Clips with GSAP animation show diamond markers on the timeline; each diamond is a keyframe (a point where a property value is set).
- Start diamond = where the tween begins (e.g.
x: 0); end diamond = where it ends (e.g.x: 1000). Multiple tweens → multiple diamond pairs. - Diamonds are synthesized automatically from every
.to(),.from(), and.fromTo()call.
Editing animation properties (Design Panel)
Selecting an animated element opens the Animation section:
- Method badge —
Animate/Animate In/Animate Out(maps to.to()/.from()/.fromTo()) - Timing — Length (duration) and Starts at (timeline position)
- Speed — the GSAP ease (e.g.
power2.inOut,back.out(3)) with a visual speed-curve preview - Properties — each animated property (Move X, Move Y, Scale, Opacity, …) with its target value
Edits apply immediately via soft reload; the Code tab shows the generated GSAP, which “renders identically in preview and headless export.”
Arc Motion
Converts a straight-line x/y animation into a curved path using GSAP’s MotionPathPlugin.
- When: an element has both
xandyin a single.to()tween — add-to-cart arcs, throw/toss effects, any motion that should feel physical. - Curviness slider:
0straight ·1gentle arc ·1.5–2.0smooth throw (recommended) ·3.0extreme loop. - Auto-Rotate (optional): element rotates to face its direction of travel (“thrown” vs “floating” feel).
- Toggling OFF restores the original flat
x/ytween values.
Generated code (the MotionPathPlugin CDN script is added automatically):
tl.to("#element", {
scale: 0.4,
opacity: 0,
duration: 1.0,
ease: "power2.inOut",
motionPath: {
path: [{x: 0, y: 0}, {x: 1400, y: -280}],
curviness: 1.5,
autoRotate: true
}
}, 1.0);Arc Motion synthesizes waypoints from {x: 0, y: 0} (start) to {x: targetX, y: targetY} (end). For intermediate waypoints, edit the motionPath.path array directly in the Code tab.
Gesture Recording
- Select an element, click Record gesture or press
R— the timeline starts playing. - Drag the element in the preview; pointer motion is sampled at ~60fps with a trail overlay.
- Press
Ragain (or let the timeline end) to stop: motion is simplified (~180 raw samples → 5–15 clean keyframes) and written to the GSAP script immediately. - Timeline seeks back to the recording start to review; Cmd+Z undoes.
Computed timelines (helpers, loops, dynamic data)
Studio reads the timeline statically, so helper-built, looped, or data-driven tweens still show every keyframe at its true time (and Arc Motion still activates for motionPath tweens even when the path comes from a variable). How a keyframe is edited depends on how it was authored:
- Literal tweens (
tl.to("#x", { x: 100 }, 1.3)) — edit directly in the Design Panel. - Helper / loop tweens — one source line (e.g.
addCycle(1.0, ...)) expands into many runtime tweens, so a single edit is ambiguous. The card shows a “Generated byaddCycle()— not directly editable” notice with an Unroll to edit action that rewrites the helper/loop into explicit literal tweens (a visual no-op — identical render); undo restores the helper. - Computed-value tweens (rare, runtime-derived, can’t resolve/unroll) — stay display-only; edit in the Code tab. Uncommon because HyperFrames compositions are deterministic.
Clipboard context (hand state to an AI agent)
The clipboard icon next to the element name copies structured context:
Element: Title (#title)
File: index.html:15
Position: x=100, y=40
Size: 264×43
Tag: <div>
Animation: from() 0.5s at 0s, ease: power2.out
Properties: x: -40, opacity: 0
Paste it into an agent prompt to give spatial context (position, size, animation, source location). This is the keyframe-editing analog of the inspector’s Ask agent bundle. ^[inferred]
Studio Manual DOM Editing
A narrow, deterministic visual editing layer over authored HTML — not a general-purpose visual builder. Studio builds a DomEditSelection + DomEditCapabilities object per selection and only exposes interactions it can round-trip back to source.
What shipped
- Select supported elements directly in the preview; an editor-owned overlay (Studio chrome, not injected into content) shows selection bounds.
- Move and resize on canvas when geometry is safe; detach eligible layout-controlled layers via an explicit
Make movableaction. - Edit style from the right-side
Designinspector; edit text layers (including empty values); add/remove child text layers for multi-text selections. - Edit solid fills, gradients, project-asset image fills, external image fills, opacity, radius, flex metadata, typography, and blend mode.
- Drill into nested compositions from master view; generate an element-scoped
Ask agentprompt bundle from the inspector header.
The overlay uses Studio-owned pointer handling in DomEditOverlay.tsx — it does not use Moveable. There is no floating action toolbar; Ask agent lives in the inspector header and style controls live in the Design panel.
Capability gating
- Move requires: a stable patch target ·
position: absoluteorfixed·left/topresolving to pixel values · not transform-driven (transform: none). - Resize requires move already allowed plus safely patchable pixel
widthand/orheight. - Detach from layout (
Make movable): for block-ish layers whose position is owned by flex/grid/normal flow. It measures the visual rect relative to the composition root and writes conservative inline geometry —position: absolute, pixelleft/top/width/height,margin: 0— instead of silently converting on drag. Inline text nodes are not detached. - Text editing: only for safe text-bearing selections (
div,span,p,strong, headings), self or leaf child text layers, empty values, and not composition hosts. - Blocked drag shows a toast: layout-owned layers point to
Make movable; transform-driven/unsafe targets explain that direct move/resize is limited to absolute/fixed pixel geometry with no transform-driven layout.
A node needs a stable patch target to be useful at all: an id, a stable selector, a selector index scoped to the correct source file, or a composition-host mapping in master view.
Nested composition rules
- Master view: clicking inside a nested composition maps back to the composition host; the host can move as a whole when its geometry is safe; inner-node geometry is not directly editable here; double-click drills in.
- After drill-down: selections resolve normally, direct move/resize returns if the inner node meets the capability rules, and text/fill/gradient/image/radius/opacity/typography edits apply to the inner node.
Source patching model
Authored HTML stays the source of truth. The flow (via packages/studio/src/utils/sourcePatcher.ts):
- user selects/manipulates an element in the preview
- Studio resolves a stable target
- preview updates optimistically for interaction feedback
- patch is written back to source
- preview refreshes and selection is reattached
Patch types: inline style patches · attribute patches (timeline-linked editing paths) · text-content patches · detach-from-layout style patches.
Structured inspector controls
- Gradient editor — a parsed gradient model (not a raw CSS field):
linear/radial/conic+ repeating variants, multiple stops (click-to-insert / remove), angle, radial shape/size, radial/conic center; serializes back tobackground-image. - Image fill — pick an existing project asset, upload (also adds to Assets tab), preview, or enter an external URL; serializes to
background-image: url(...)and rewrites asset URLs so nested subcomposition previews resolve. - Color editor — a custom viewport-clamped popover (not the native dialog) with saturation/brightness crosshair, hue/alpha handles, swatch, readout, hex input; writes
rgb(...)/rgba(...)and preserves alpha. - Numeric scrubbing — wheel-over-field,
ArrowUp/ArrowDown,Shiftfor larger steps,Altfor finer steps, across layout metrics and any clean value+unit field.
Out of scope today
Rotation · arbitrary transforms · snapping/alignment guides · multi-select · marquee selection · freeform editing of every DOM node regardless of layout model · editing nested subcomposition internals from master view without drill-down · auto-conversion to absolute on drag without confirmation · direct geometry editing of inline text spans.
Bottom line (from the docs): the deterministic, round-trippable scope “is the reason the current feature feels reliable instead of deceptive.”
Try It
- In Studio, drag a caption clip to a higher timeline row and confirm in the HTML that
data-track-indexand inlinez-indexchanged — the source stays inspectable. - Right-trim a GSAP card to end it sooner (
data-duration); note there’s no left handle. Then trim the start of avideoclip and watchdata-start+data-media-startmove together. - Select an element with both Move X and Move Y, toggle Arc Motion ON, set Curviness to ~1.7, enable Auto-Rotate, and check the Code tab for the generated
motionPathblock. - Press
R, drag an element through the preview, stop, and inspect the 5–15 synthesized keyframes; Cmd+Z to retry. - Select a flex/grid child, hit
Make movableto detach it to absolute pixel geometry, then nudge X/Y with the arrow keys (holdShift/Altfor step size).
Open Questions
- Roadmap/timing for true front-trim on generic motion clips (a playback-offset model for GSAP elements) is not stated in the docs.
- Whether the keyframe-editing clipboard context and the DOM inspector’s
Ask agentbundle share one prompt-generation path (domEditing.ts) is not explicitly confirmed in the sources. - The exact pointer-path simplification algorithm used by gesture recording (beyond “~180 → 5–15 keyframes”) is not documented.