Commit Graph
808 Commits
Author SHA1 Message Date
Miguel ÁngelandClaude Opus 4.6 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 ÁngelandClaude Opus 4.6 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 ÁngelandClaude Opus 4.6 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 ÁngelandClaude Opus 4.6 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 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 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 ÁngelandClaude Opus 4.6 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 ÁngelandClaude Opus 4.6 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
James 1545763ea3 fix(cli,producer): cross-multiply aspect check, CLI HDR guard, honest banner 2026-05-07 16:58:25 +00:00
James 5260429dd9 docs(4k): add asset-scaling reality check and reflect Studio dropdown 2026-05-07 16:58:25 +00:00
James e07aeba213 feat(cli): add --resolution flag to hyperframes render for one-line 4k 2026-05-07 16:58:25 +00:00
James Russo c1c7ba999a Merge pull request #661 from heygen-com/05-07-feat_cli_add_--resolution_flag_to_hyperframes_init_for_4k_scaffolding
feat(cli): add --resolution flag to hyperframes init for 4k scaffolding
2026-05-07 07:55:13 -07:00
James Russo a50aaa55cb Merge pull request #662 from heygen-com/05-07-fix_engine_byte-budget_the_frame_data_uri_cache_to_bound_memory_at_4k
fix(engine): byte-budget the frame data uri cache to bound memory at 4k
2026-05-07 07:31:06 -07:00
Vance Ingalls edac92b431 docs: add texture mask text catalog entry (#650)
* feat(registry): add texture mask PNGs for texture-mask-text component

* feat(registry): add texture-mask-text CSS snippet

* feat(registry): add registry-item.json for texture-mask-text

* feat(registry): add texture-mask-text demo composition

* feat(registry): register texture-mask-text component in manifest

* style: format texture-mask-text files with oxfmt

* fix: set mask-image directly on texture classes instead of via CSS custom property

url() inside CSS custom properties doesn't resolve correctly with mask-image
in some browsers. Move mask-image declarations to each texture class directly.

* docs: add texture mask text catalog entry

* test: lint texture mask text usage

* fix: harden texture mask text docs and lint

* fix: stabilize texture mask asset paths

* fix: address texture catalog review feedback

* fix: harden texture mask text instructions

* docs: remove texture catalog intro copy

* docs: use canonical texture preview URL

* docs: use cdn texture mask assets

* fix: escape catalog frontmatter safely

* test: stabilize windows render cli test

* test: pin texture catalog instructions
2026-05-07 00:23:36 -07:00
James 8355b39ffc fix(engine): skip caching oversized frames + add eviction telemetry 2026-05-07 06:10:26 +00:00
James 8203005488 fix(engine): byte-budget the frame data uri cache to bound memory at 4k 2026-05-07 06:10:26 +00:00