Commit Graph

816 Commits

Author SHA1 Message Date
Miguel Ángel e0e11acec6 fix(studio): block element selection while composition is loading
Prevent users from selecting elements in the preview while the
composition is still loading (showing "Loading composition" overlay).
Selection and hover highlighting are suppressed until the player fires
the ready event.

Also reverts motion panel and manual drag editing defaults to false —
these were accidentally set to true during the PR #693 merge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 21:50:30 +00:00
Miguel Ángel 94a69598d2 fix(runtime): update clock duration when root timeline is late-bound
Compositions with external sub-compositions (like apple-presentation
with 7 slides) load child compositions via fetch(). The root GSAP
timeline is only bound after all external compositions finish loading,
but the TransportClock duration was only set during initial setup.

When bindRootTimelineIfAvailable runs after the external compositions
load, it captures the root timeline but never updates the clock.
player.getDuration() continues returning 0, so the player's probe
interval never fires the 'ready' event, and the Studio shows "Loading
composition" indefinitely.

Now bindRootTimelineIfAvailable updates clock.setDuration when the
root timeline is late-bound. Guarded with try/catch for the early call
site where clock is not yet initialized (temporal dead zone).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 21:41:25 +00:00
Miguel Ángel ed87fd57ec chore: release v0.6.0-alpha.4 v0.6.0-alpha.4 2026-05-09 20:07:00 +00:00
Miguel Ángel a75b6e6c00 Merge pull request #692 from heygen-com/feat/studio-inspector-selection-ux
feat(studio): simplify inspector selection UX
2026-05-09 22:06:41 +02:00
Miguel Ángel 4730f1db4b chore: merge next into feat/studio-inspector-selection-ux 2026-05-09 20:06:25 +00:00
Miguel Ángel 513deb444b Merge pull request #693 from heygen-com/fix/alpha-e2e-fixes
fix: alpha preview e2e fixes — exports, init templates, EPIPE crash
2026-05-09 22:04:23 +02:00
Miguel Ángel 45adf4805f fix(studio): prevent read-only property crash in manual edit wrappers
The seek/play/applyAfter wrapper functions in manualEdits.ts crashed
with "Cannot set property X which has only a getter" when the player
or timeline objects define seek/play as getter-only properties. This
prevented ALL manual edits (position, rotation, size) from persisting
to disk — the error thrown during applyCurrentStudioManualEditsToPreview
aborted the save queue.

Wrapped all three property assignments in try/catch so wrapping
gracefully degrades when the target object is non-configurable.

Verified: position edit (X=42px) now persists to
.hyperframes/studio-manual-edits.json and survives page refresh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 20:01:43 +00:00
Miguel Ángel 75bc3b4925 fix(studio): revert motion panel default to false
Motion panel stays opt-in via env var per product direction. Only
the Design panel is enabled by default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 19:44:52 +00:00
Miguel Ángel c5dd7cae39 fix(studio): prevent browser launch timeout from crashing dev server
The shared Puppeteer browser pool in getSharedBrowser() could throw a
30s TimeoutError during launch. This error propagated as an uncaught
rejection and killed the vite process, even though generateThumbnail
had its own try/catch — the browser launch promise rejected outside
that scope. Now getSharedBrowser itself catches launch failures and
returns null, so thumbnails degrade gracefully instead of crashing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 18:45:11 +00:00
Miguel Ángel f3e2caf687 fix(studio): stale selection, rotation control, design panel polish
Fixes and improvements based on power-user testing feedback:

1. Fix stale selection after style edits — handleDomStyleCommit now
   calls refreshDomEditSelectionFromPreview after persisting, matching
   every other commit handler. Without this, the PropertyPanel showed
   frozen computedStyles after color/radius/shadow edits, making it
   look like editing "didn't work." Also adds error handling around
   the persist call.

2. Add rotation field to the Design panel Layout section — reads the
   current rotation angle from the manual edit manifest and commits
   via the existing handleDomRotationCommit handler.

3. Enable motion panel by default — STUDIO_MOTION_PANEL_ENABLED now
   defaults to true so the Motion tab is discoverable without env vars.

4. Color controls only when element has color — fill color section now
   only shows when the element has an explicit non-transparent
   background-color. Text color shows only when the element has a
   color style. Prevents showing color pickers on elements where
   color edits have no visible effect.

5. Exclude canvas from selection — added "canvas" to
   DOM_LAYER_IGNORED_TAGS so canvas elements are not selectable in the
   preview or listed in the layer panel.

6. Multi-selection feedback — shows "N elements selected" with
   guidance instead of the generic empty state when multiple elements
   are selected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 18:41:58 +00:00
Miguel Ángel 1e0ca35fd6 fix(studio): thumbnail crash, feature defaults, multi-select UX, fps selector
Power-user audit fixes for the alpha studio:

- vite.config.ts: wrap thumbnail generation in try/catch so Puppeteer
  TimeoutError doesn't crash the entire vite dev server as an uncaught
  rejection. Close the page on error to prevent browser session leaks.

- manualEditingAvailability.ts: enable motion panel and manual canvas
  drag editing by default (were both false, undiscoverable without
  knowing the env vars).

- PropertyPanel.tsx: show "N elements selected" feedback when multiple
  elements are selected instead of the generic "Select an element"
  empty state.

- RenderQueue.tsx + App.tsx: add FPS selector (24/30/60) to the render
  export bar instead of hardcoding 30fps. Pass the user's choice
  through to startRender.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 18:08:45 +00:00
Miguel Ángel d34a5ed2cf fix(studio): handle raster inspector clicks 2026-05-09 02:24:35 -07:00
Miguel Ángel de876a4fcc fix(studio): keep notion preview playback moving 2026-05-09 00:34:43 -07:00
Miguel Ángel 7d0d903417 fix: alpha preview e2e fixes — exports, init templates, EPIPE crash
Three bugs found via automated e2e testing of the v0.6.0-alpha preview:

1. core: add missing package.json export specifiers for
   studio-api/manual-edits-render-script and
   studio-api/studio-motion-render-script — the alpha.3 npm publish
   failed because the studio build could not resolve these sub-paths.

2. cli: fix init --example creating empty projects — tsup leaves empty
   template directories in dist/ during the build, causing
   existsSync(templateDir) to return true and skip the remote fetch
   fallback. Now checks for index.html inside the dir instead.

3. engine: fix unhandled EPIPE crash in streaming encoder — ffmpeg
   stdin/stdout had no error handlers, so a write after the ffmpeg
   process exits throws an uncaught error that crashes the process.

Verified with 8 consecutive e2e iterations (424 test runs, 0 flaky).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 07:21:06 +00:00
Miguel Ángel 5ddf0285f5 feat(studio): simplify inspector selection ux 2026-05-08 21:40:12 -07:00
Miguel Ángel 1781f6bf1f chore: release v0.6.0-alpha.3 v0.6.0-alpha.3 2026-05-09 02:56:37 +00:00
Miguel Ángel a785c05c53 chore: ignore .claude directory 2026-05-09 02:56:37 +00:00
Miguel Ángel c29c159a1e chore: merge main into next 2026-05-09 02:56:24 +00:00
Miguel Ángel e47dad0dbf Merge pull request #687 from heygen-com/feat/studio-shader-loading-state
feat: show composition loading in Studio
2026-05-09 04:51:02 +02:00
Miguel Ángel ef79a2b14d feat: disable Studio timeline while composition loads 2026-05-08 19:40:49 -07:00
Miguel Ángel 5a41ea44e1 Merge pull request #689 from heygen-com/feat/studio-auto-open-timeline-layers
feat: auto-open timeline clip layers
2026-05-09 03:27:38 +02:00
Miguel Ángel ba29781c56 feat: auto-open timeline clip layers 2026-05-08 18:23:49 -07:00
Miguel Ángel 48341aa776 feat: show composition loading in studio 2026-05-08 17:59:50 -07:00
Miguel Ángel c2738364aa chore: release v0.6.0-alpha.2 v0.6.0-alpha.2 2026-05-08 17:34:24 -07:00
Miguel Ángel 75618d9425 Merge pull request #686 from heygen-com/feat/studio-default-inspector-panels
feat(studio): enable inspector layers by default
2026-05-09 02:32:18 +02:00
Miguel Ángel 7c9648a143 fix(studio): keep motion panel opt-in 2026-05-08 17:30:21 -07:00
Miguel Ángel 6eee626980 feat(studio): enable inspector panels by default 2026-05-08 17:27:08 -07:00
Miguel Ángel d6db60c26a chore: release v0.6.0-alpha.1 v0.6.0-alpha.1 2026-05-08 16:37:50 -07:00
Miguel Ángel 995ec700d1 feat(studio): add alpha editor layer inspector (#683)
## Problem

The Studio animation/manual-editing alpha had grown into one oversized PR. Reviewers need the actual user-facing editor changes separated from the lower-level preview API support, and the alpha controls need safer defaults while we keep testing manual dragging and the motion panel.

## What this fixes

- Moves Clip Layers into the left sidebar as a takeover surface so it no longer looks like part of the video canvas.
- Hides the normal left-panel tabs while Clip Layers is open, keeps nested layer counts visible, and keeps timeline clip inspector buttons available.
- Keeps Motion and preview manual dragging behind env flags: `VITE_STUDIO_ENABLE_MOTION_PANEL` and `VITE_STUDIO_ENABLE_PREVIEW_MANUAL_DRAGGING`.
- Keeps the default inspector focused on Design/Renders while preserving the opt-in GSAP motion panel for alpha testing.
- Carries the timeline thumbnail/player performance work and selection timing fixes needed for the layer inspector flow.
- Adds/updates tests for layer inspection, motion availability, DOM editing, timeline behavior, and player seeking.

## Root cause

The old overlay-based layer picker competed visually with the preview content, and the motion/manual-dragging alpha controls were always present even when the team wanted to test the design panel without those experimental surfaces. Splitting this into a Graphite stack also avoids reviewing Core API changes and Studio UI changes in one giant diff.

## Verification

### Local checks

- `bun run --filter @hyperframes/studio test -- src/components/editor/TimelineLayerPanel.test.ts src/components/editor/manualEditingAvailability.test.ts src/components/editor/PropertyPanel.test.ts src/components/editor/domEditing.test.ts src/components/editor/studioMotion.test.ts src/utils/timelineInspector.test.ts src/player/components/Timeline.test.ts src/player/components/timelineEditing.test.ts src/player/hooks/useTimelinePlayer.test.ts`
- `bun run --filter @hyperframes/core test -- src/studio-api/routes/preview.test.ts src/studio-api/routes/thumbnail.test.ts src/studio-api/helpers/studioMotionRenderScript.test.ts`
- `bun run --filter @hyperframes/core build`
- `bun run --filter @hyperframes/studio build`

### Browser verification

Tested with `agent-browser` against `hf-manual-editing-demo` on the split stack.

- Default flags on `http://127.0.0.1:5298/?v=graphite-default-proof#project/hf-manual-editing-demo`: Clip Layers opens in the left sidebar, Design/Renders remain visible, and Motion is hidden.
- Env flags on `http://127.0.0.1:5299/?v=graphite-env-proof#project/hf-manual-editing-demo`: Inspector exposes the Motion tab.
- Screenshots: `qa-artifacts/graphite-stack/default-loaded.png`, `qa-artifacts/graphite-stack/default-layer-panel.png`, `qa-artifacts/graphite-stack/env-enabled-inspector.png`, `qa-artifacts/graphite-stack/env-enabled-motion-tab.png`.
- Recording: `qa-artifacts/graphite-stack/default-layer-panel-flow.webm`.

## Notes

- This PR intentionally depends on #682 for the Core Studio API support.
- `qa-artifacts/` remains local/untracked.
- Existing PR #680 is superseded by this Graphite stack.
2026-05-09 01:25:26 +02:00
Miguel Ángel e51c11c6f9 feat(studio): add alpha editor layer inspector 2026-05-08 23:24:25 +00:00
Miguel Ángel 4c211d5085 feat(core): add studio animation preview APIs (#682)
## Problem

The Studio alpha editor work needs runtime/server support before the UI can be reviewed cleanly: previews and thumbnails need cache-aware project signatures, and render paths need a deterministic way to apply Studio-authored GSAP motion during preview/render without mixing that logic into the Studio UI commit.

## What this fixes

- Adds a project signature helper used by Studio preview/thumbnail responses.
- Adds the Studio motion render-body script helper and package export.
- Extends preview and thumbnail route coverage for the animation/layer inspector stack.
- Keeps this bottom PR scoped to Core Studio API support so the upstack UI PR can stay reviewable.

## Root cause

The previous single PR mixed server API support with the full editor surface. Reviewers could not reason about whether deterministic preview/thumbnail behavior was correct independently from the UI interactions.

## Verification

### Local checks

- `bun run --filter @hyperframes/core test -- src/studio-api/routes/preview.test.ts src/studio-api/routes/thumbnail.test.ts src/studio-api/helpers/studioMotionRenderScript.test.ts`
- `bun run --filter @hyperframes/core build`
- `bun run --filter @hyperframes/studio build` from the top of the stack

### Browser verification

Browser proof is exercised in the upstack Studio UI PR because this PR only adds the server/runtime support. The full stacked behavior was verified at:

- `qa-artifacts/graphite-stack/default-layer-panel.png`
- `qa-artifacts/graphite-stack/default-layer-panel-flow.webm`
- `qa-artifacts/graphite-stack/env-enabled-motion-tab.png`

## Notes

- This is the bottom of the Graphite stack.
- Local browser artifacts are intentionally untracked and not part of the PR diff.
2026-05-09 01:23:46 +02:00
Miguel Ángel 74d8025dcb feat(core): add studio animation preview APIs 2026-05-08 16:13:43 -07:00
Miguel Ángel ae343bfdc8 chore: release v0.5.5
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.5.5
2026-05-08 15:00:29 +00:00
Miguel Ángel 75dcfd98cf Merge pull request #675 from heygen-com/fix/webaudio-future-clip-scheduling 2026-05-08 16:59:17 +02:00
Miguel Ángel 38522f996e fix(runtime): schedule future WebAudio clips with delay instead of playing immediately
Clips whose compositionStart is ahead of the current timeline position
were starting immediately because sourceNode.start() always received
when=0. Use the AudioContext scheduling API to defer future clips:
sourceNode.start(ctx.currentTime + delay, mediaStart).

Closes #674

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-08 14:56:33 +00:00
Miguel Ángel 8de7ad7f61 chore: release v0.5.4 v0.5.4 2026-05-07 23:22:15 -07:00
Miguel Ángel f761ee2624 fix(player): drive src URL timelines without runtime (#673)
* fix(player): drive src URL timelines without runtime

* fix(player): pause direct timeline after seek
2026-05-08 08:19:29 +02:00
Miguel Ángel b009288df7 feat(runtime): single-clock transport — eliminate pause/play audio drift (#671)
Replace the two-clock architecture (GSAP rAF ticker + HTMLMediaElement
pipeline reconciled by a 50ms polling loop) with a single TransportClock.
GSAP is always paused and seeked to clock.now() on each rAF tick.
Drift between visual timeline and audio is structurally impossible.

Architecture:

  TransportClock.now() ──rAF──▶ timeline.seek(t) + el.currentTime
       ▲
  AudioContext.currentTime (~21µs)  ← WebAudio active
       OR
  audio.currentTime (~33ms)         ← HTMLMediaElement fallback
       OR
  performance.now() (~1ms)          ← no audio

Key changes:
- TransportClock class with monotonic + audio-master clock sources
- WebAudioTransport: routes audio through AudioBufferSourceNode for
  sample-accurate scheduling, falls back gracefully to HTMLMediaElement
- rAF tick loop replaces 50ms setInterval poll; GSAP always paused
- Strict sync (40ms threshold, consecutive-sample gated) + forceSync
  on play/pause/seek transitions for sub-frame media accuracy
- Buffer-stall: visuals freeze when audio is buffering instead of
  running ahead
- Frame quantization preserved in seek/renderSeek (parity contract)

Browser-verified: 0.0ms drift after 40 pause/play cycles (was 400ms+).

Also fixes: CDN script HTML error responses in validate (pre-existing).

54 tests across clock, clock-drift, webAudioTransport, and media.

Closes #668
2026-05-08 07:53:46 +02:00
James Russo 7bf30d5423 Merge pull request #666 from heygen-com/05-07-fix_engine_supersample_screenshot_capture_to_honor_devicescalefactor
fix(engine): supersample screenshot capture to honor deviceScaleFactor
2026-05-07 12:08:42 -07:00
James Russo 65727e33d9 Merge pull request #665 from heygen-com/05-07-refactor_dedupe_resolution_presets_and_clean_up_4k_stack
refactor: dedupe resolution presets and clean up 4k stack
2026-05-07 11:47:46 -07:00
James Russo ef13841fa3 Merge pull request #664 from heygen-com/05-07-feat_studio_add_resolution_selector_to_render_export_bar
feat(studio): add resolution selector to render export bar
2026-05-07 10:56:57 -07:00
James Russo 441640813a Merge pull request #663 from heygen-com/05-07-feat_cli_add_--resolution_flag_to_hyperframes_render_for_one-line_4k
feat(cli): add --resolution flag to hyperframes render for one-line 4k
2026-05-07 10:40:59 -07:00
James 453bd6e313 fix(engine,producer): reject alpha+supersample, unit-test clip plumbing 2026-05-07 16:58:26 +00:00
James 0eaa54e000 fix(core,engine): derive CanvasResolution from CANVAS_DIMENSIONS, snapshot eviction value 2026-05-07 16:58:26 +00:00
James bc02b8810c fix(studio): exhaustively type RESOLUTION_OPTIONS and document layout coupling 2026-05-07 16:58:26 +00:00
James 385917ea59 fix(engine): supersample screenshot capture to honor deviceScaleFactor 2026-05-07 16:58:26 +00:00
James 2b2281d490 refactor: dedupe resolution presets and clean up 4k stack 2026-05-07 16:58:26 +00:00
James 0c026bb0f6 fix(studio): forward outputResolution from vite dev adapter to producer 2026-05-07 16:58:26 +00:00
James 25edba803a feat(studio): add resolution selector to render export bar 2026-05-07 16:58:26 +00:00
James 2d3ad953ee ci: bump pinned BtbN ffmpeg release to 2026-04-30 monthly snapshot
The autobuild-2026-04-23-13-16 release was rotated out of BtbN's
recent-dailies window, returning 404 on the Windows test/render jobs.
Switch to the 2026-04-30 month-end snapshot, which BtbN keeps long-term
(visible in the persistent monthly-snapshot history).
2026-05-07 16:58:25 +00:00