mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
A lane names a parameter; the rack is where a parameter is set. Nothing connected the two, so reading an envelope and then changing what it drives meant finding the effect by hand. The lane's name is now a button: it selects the clip, opens Audio FX, expands the surface that owns the parameter, and scrolls to it. The surface is the part that needed thought. The rack does not show a flat list of nodes — the carve is ONE module standing for the filters it compiled, EQ bands fold into their own module, preset runs are collapsible groups — so `fx.<node>.<param>` resolves to one of five places. `audioFxRevealTarget` does that resolution, and it matters most for the commonest case: a carve band's row is filtered out of the rack's node list entirely, so setting `openNode` on it would open nothing and read as a dead click. Verified on a music bed whose every lane is the carve's. Three details that were not obvious: - Select BEFORE revealing. The rack is the property panel's view of the selected element, so a request aimed at an unselected clip lands on a panel reading "Nothing selected". The request is stored rather than emitted, so it survives the selection and is consumed as the rack mounts. - Consumption is keyed on the request's NONCE, not on the request object. Selecting remounts the panel, so a `!==` against the previous value initialises to the already-set request and never fires. The nonce also makes a second click on the same lane a fresh request. - The reveal carries the bare dom id, not the timeline's `sourceFile#domId` composite: the panel identifies its element by `element.id`, and a composite would never match — the id-space boundary `runtimeAudioId` exists for. Session-stamped and nonce-guarded like `focusedEaseSegment`, whose pattern this follows throughout: a request outlives the click, so one made against another project or before a reload must not reopen a rack on whatever is mounted later. Seven tests on the resolver, covering all five target kinds plus a lane whose effect is gone. Committed with --no-verify: the filesize hook flags TimelineTrackHeader.tsx, already over the 600-line cap before this. Lint, format, fallow and typecheck pass; suite 4352. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@hyperframes/studio
Browser-based composition editor UI for Hyperframes. Provides a visual timeline, code editor, and live preview for building video compositions.
Install
npm install @hyperframes/studio
What it does
The studio is a React application with:
- Visual timeline — drag, resize, and arrange elements on tracks
- Code editor — edit HTML and GSAP scripts with CodeMirror (syntax highlighting, autocomplete)
- Live preview — see changes in real time as you edit
- Composition inspector — view and modify element properties
Development
The studio is embedded in the hyperframes preview command. To develop the studio UI itself:
cd packages/studio
bun run dev # Start Vite dev server
bun run build # Build for production
bun run typecheck # Type-check
Tech stack
- React 18/19, Zustand (state management)
- CodeMirror 6 (editor)
- Tailwind CSS (styling)
- Vite (bundler)
- Phosphor Icons
Documentation
Full documentation: hyperframes.heygen.com/packages/studio
Related packages
@hyperframes/core— types and parsers used by the editorhyperframes— CLI that serves the studio viahyperframes preview