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 → inline z-index. Split/slip/slide/ripple/roll semantics are intentionally not implemented yet.
  • Front-trim is media-only. video/audio (and wrappers with data-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 curved motionPath (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/fixed position + pixel left/top + no transform; resize additionally needs patchable pixel width/height. Layout-owned layers get an explicit Make movable instead 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:

ActionGesturePersists to
Move clip in timedrag horizontallydata-start
Move clip between rowsdrag verticallydata-track-index
Change visual stackingreorder rows (top renders above)inline z-index
Trim end of clipdrag right handledata-duration
Trim start of media clipdrag 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 by data-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 badgeAnimate / 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 x and y in a single .to() tween — add-to-cart arcs, throw/toss effects, any motion that should feel physical.
  • Curviness slider: 0 straight · 1 gentle arc · 1.5–2.0 smooth throw (recommended) · 3.0 extreme loop.
  • Auto-Rotate (optional): element rotates to face its direction of travel (“thrown” vs “floating” feel).
  • Toggling OFF restores the original flat x/y tween 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 R again (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 by addCycle() — 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 movable action.
  • Edit style from the right-side Design inspector; 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 agent prompt 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: absolute or fixed · left/top resolving to pixel values · not transform-driven (transform: none).
  • Resize requires move already allowed plus safely patchable pixel width and/or height.
  • 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, pixel left/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):

  1. user selects/manipulates an element in the preview
  2. Studio resolves a stable target
  3. preview updates optimistically for interaction feedback
  4. patch is written back to source
  5. 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 to background-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, Shift for larger steps, Alt for 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-index and inline z-index changed — 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 a video clip and watch data-start + data-media-start move 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 motionPath block.
  • 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 movable to detach it to absolute pixel geometry, then nudge X/Y with the arrow keys (hold Shift/Alt for 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 agent bundle 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.