Commit Graph
278 Commits
Author SHA1 Message Date
Vance IngallsandClaude Opus 4.6 614a67dfd3 fix: caption init race condition, auto-save, and panel auto-open
- Remove store reset from useEffect cleanup — was wiping state on dep changes
  and breaking auto-save subscription
- Move panel auto-open into useEffect instead of during render
- Add fallback 500ms poll alongside postMessage listener for initial load

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:13 -07:00
Vance IngallsandClaude Opus 4.6 f2718783c2 fix: use runtime postMessage events to detect caption composition loading
Replace polling with a message listener for hf-preview state/timeline
events. These fire after loadExternalCompositions completes, guaranteeing
.caption-group elements exist in the DOM. Eliminates the race condition
on initial page load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:13 -07:00
Vance IngallsandClaude Opus 4.6 96866cddf6 feat: auto-detect captions from any composition, edit from master view
Caption edit mode now activates automatically when .caption-group elements
are found in the iframe DOM. Works from index.html (master) without
requiring drill-down into the captions sub-composition. Finds the captions
source file via data-composition-src attribute.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 76a667c281 feat: auto-activate caption editor when viewing captions composition
- Caption overlay and hover states always active on captions compositions
- Clicking a word auto-opens the property panel
- Remove Edit Captions button — edit mode activates automatically
- Reset edit mode when navigating away from captions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 0e1148556f feat: arrow key nudge for selected caption words
1px per press, 10px with Shift held. Syncs to store and auto-saves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 f321269a65 refactor: strip property panel to position, scale, rotation only
Remove typography, color, opacity, stroke, and background controls.
Keep only Position (X/Y) and Transform (Scale/Rotation) — the controls
that work reliably with the wrapper-based override system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 9dd394eb70 feat: active/dim color states for caption word overrides
Replace single "color" with activeColor (spoken) and dimColor (inactive).
Runtime hook modifies existing GSAP color tweens by detecting dim vs active
states via opacity heuristic. Property panel shows both color pickers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 613ed774ae refactor: remove preview refresh suppression during caption edit mode
No longer needed — caption overrides are a JSON data file, not HTML patches.
The runtime hook re-applies overrides on every reload, so preview refresh
during editing is safe and ensures the preview stays in sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 933b72b633 feat: auto-save caption overrides on model change
Replace manual Save button with 800ms debounced auto-save. Writing to
caption-overrides.json is safe because preview refresh is suppressed
during caption edit mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:12 -07:00
Vance IngallsandClaude Opus 4.6 b7d7a1c2b0 fix: wrapper-aware element resolution for caption overlay
- getWordEl skips wrapper spans and finds actual word elements inside them
- readWordBoxes handles wrapped words in position calculations
- getOrCreateWrapper detects if element IS a wrapper to prevent double-wrapping
- Remove debug logging from save

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 bf27578755 fix: caption overrides runtime hook — run in both load paths, write to project root
- applyCaptionOverrides() now runs both when compositions load async AND when
  already ready (standalone composition view)
- Overrides file written to project root (not compositions/) to match <base href>
- Remove debug logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 a60c9e523b feat(lint): enforce .caption-group > span convention for caption overrides
- New lint rule `caption_word_structure`: warns when caption compositions don't
  use <span> word elements inside .caption-group containers
- Document required DOM structure in the captions skill
- Document word ID field in transcript format

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 b6bdce065e feat: wrapper-based caption overrides — preserve all GSAP animations
Instead of killing transform tweens, wrap each overridden word span in an
inline-block wrapper span. Editor transforms (position, scale, rotation)
are applied to the wrapper while the inner span keeps all GSAP entrance,
exit, and karaoke animations intact.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 7c0f825d72 feat: caption overrides with stable word IDs and killTweensOf
- Add optional `id` field to transcript Word interface, assigned as `w{index}` during normalization
- caption-overrides.json uses `wordId` (preferred) with `wordIndex` fallback
- Runtime hook calls gsap.killTweensOf for overridden transform properties before applying
- Studio parser carries wordId through from transcript to segments
- Add typecheck to lefthook pre-commit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 5d2efb24c1 feat: replace HTML patching with caption-overrides.json data file
- New caption-overrides.json format: [{wordIndex, x, y, scale, rotation, color, ...}]
- Runtime hook in packages/core applies overrides via gsap.set() after compositions load
- Studio writes/reads caption-overrides.json instead of injecting code into HTML
- Original composition source is never modified
- Remove old parseExistingOverrides and source patching code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:11 -07:00
Vance IngallsandClaude Opus 4.6 b00f062bdf chore: revert unrelated LintModal changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:10 -07:00
Vance IngallsandClaude Opus 4.6 7c07d09cf3 chore: add typecheck to lefthook pre-commit and fix container type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:10 -07:00
Vance IngallsandClaude Opus 4.6 cb335ba2a7 feat(studio): caption designer canvas controls, real-time editing, and save-as-patch
- Canvas: move (translate), scale, and rotate handles on selected words via gsap.set()
- Property panel: real-time style updates applied directly to iframe DOM
- Save: patches original source with gsap.killTweensOf + gsap.set per edited word
- Parser: reads existing editor overrides on re-entry to preserve prior edits
- Suppress preview refresh during caption edit mode to prevent reload cycle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:10 -07:00
Vance Ingalls 9f73dae176 feat(studio): add caption module barrel export 2026-04-01 23:37:10 -07:00
Vance IngallsandClaude Sonnet 4.6 2e850cb360 feat(studio): add caption timeline track with word-level blocks and drag-to-retime
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:37:10 -07:00
Vance Ingalls 876a053b90 feat(studio): add caption animation panel with entrance/highlight/exit controls 2026-04-01 23:37:10 -07:00
Vance Ingalls 0233ae2361 feat(studio): wire caption property panel and parser integration 2026-04-01 23:37:10 -07:00
Vance IngallsandClaude Sonnet 4.6 97b88d86fc feat(studio): add caption property panel with typography, color, and transform controls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:37:09 -07:00
Vance IngallsandClaude Opus 4.6 9370e4fb7b feat(studio): wire caption overlay and edit mode into Studio
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:09 -07:00
Vance Ingalls fce9268304 feat(studio): add drag-to-reposition for caption segments 2026-04-01 23:37:09 -07:00
Vance Ingalls 9128524cf4 feat(studio): add caption overlay with segment selection boxes 2026-04-01 23:37:09 -07:00
Vance Ingalls 486a018dc9 feat(studio): add caption model → HTML source sync hook 2026-04-01 23:37:09 -07:00
Vance IngallsandClaude Sonnet 4.6 980ca1f750 feat(studio): add caption HTML generator
Implements generateCaptionHtml(model) which serializes a CaptionModel
into a complete captions.html HyperFrames composition with template
wrapper, CSS per-group classes, TRANSCRIPT array, and GSAP timeline
registration via window.__timelines["captions"].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:37:09 -07:00
Vance Ingalls 39712ba6e7 feat(studio): add caption editing Zustand store 2026-04-01 23:37:09 -07:00
Vance Ingalls be97bfadd6 feat(studio): parse caption styles from live iframe DOM 2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Sonnet 4.6 7b5cfea5e8 feat(studio): build caption model from transcript words
Adds `buildCaptionModel` to the caption parser — groups TranscriptWord
arrays into CaptionGroups (default 5 words each), creates CaptionSegments
with correct timing and groupIndex, and wires in DEFAULT_STYLE,
DEFAULT_CONTAINER, and DEFAULT_ANIMATION_SET. Covers 23 tests (13 new).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Sonnet 4.6 012d1afbf3 feat(studio): add transcript extraction from caption source
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:37:08 -07:00
Vance Ingalls 0d310fc05d feat(studio): add caption model types 2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Opus 4.6 3b5753c8a8 feat(captions): energy-based technique selection and mandatory quality checks
- Rewrite script-to-style mapping as energy detection table
- Add mandatory animation design requirements (karaoke baseline, technique cycling)
- Simplify dynamic-techniques.md to technique selection reference
- Add transcript quality check with automatic retry rules
- Add multilingual model guidance and decision tree

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Opus 4.6 997e1488e9 docs: add linting and formatting tooling instructions to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Opus 4.6 68821df356 fix(cli): handle unknown type in pageerror handler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:08 -07:00
Vance IngallsandClaude Opus 4.6 aa9175adc1 fix(cli): fix typecheck errors in validate command
- ConsoleMessage.type() returns "warn" not "warning"
- Type pageerror callback parameter as Error

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:07 -07:00
Vance IngallsandClaude Opus 4.6 2ba35674a0 feat(cli): add hyperframes validate command
Loads a composition in headless Chrome and reports console errors,
uncaught exceptions, and failed network requests for project assets.
Agents run this before opening the studio to catch runtime issues.

- Bundle HTML with inlined runtime (no CDN dependency)
- Minimal file server for project assets
- Captures JS errors, pageerror events, 404s on project files
- JSON output mode for programmatic consumption
- ~3s execution time, suitable as a blocking pre-preview step

Updates CLAUDE.md and compose skill to require lint + validate
before opening the studio.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:07 -07:00
Vance IngallsandClaude Opus 4.6 949ff52177 fix(studio): serve runtime locally instead of from CDN
The Vite dev server was loading the HyperFrames runtime IIFE from
cdn.jsdelivr.net. This caused compositions using window.__hyperframes
(e.g., fitTextFontSize) to fail when the CDN script didn't load in
the iframe context.

Add a /api/runtime.js endpoint to the Vite plugin that serves the
local built runtime, matching what studioServer.ts already does for
the CLI embedded server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:37:07 -07:00
Vance IngallsandClaude Opus 4.6 54863254d0 fix(skills): default to non-.en whisper models to prevent silent translation
.en models (small.en, medium.en) translate non-English audio into English
instead of transcribing it. This silently destroys the original language.

- Add non-negotiable language rule to captions skill
- Update model tables to default to models without .en suffix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:35:36 -07:00
Vance Ingalls 0686408f57 docs(captions): update audio-reactive references to match simplified pattern 2026-04-02 06:25:12 +00:00
Vance Ingalls 2cca04d7b5 refactor(captions): replace tl.call audio-reactive pattern with group-level GSAP tweens 2026-04-02 06:25:12 +00:00
Vance IngallsandClaude Opus 4.6 41d1286c33 feat(lint): warn when captions use fetch() instead of inline TRANSCRIPT
Adds two lint rules for caption compositions:
- caption_transcript_not_inline: warns when transcript is loaded via
  fetch() instead of an inline var TRANSCRIPT array
- caption_transcript_parse_error: warns when the inline TRANSCRIPT
  array is not valid JSON (common with unquoted keys + apostrophes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:12 +00:00
Vance IngallsandClaude Opus 4.6 ea52b8f4d5 docs(captions): add studio caption editor compatibility requirements
Documents the inline TRANSCRIPT requirement, JSON-quoted keys, and
CSS class conventions needed for the studio caption editor to detect
and edit captions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:12 +00:00
Vance IngallsandClaude Opus 4.6 ad807bb21f fix(captions): register timeline synchronously before audio fetch
The player needs window.__timelines registered immediately to start
playback. GSAP timelines are mutable so tl.call() entries added
later in the fetch callback still fire when seeked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:12 +00:00
Vance IngallsandClaude Opus 4.6 747dadf024 feat(captions): add overflow and audio-reactive constraints
- Never overflow: hidden on caption containers — clips glow/scale effects
- Music requires audio-reactive captions (any genre, any energy level)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:12 +00:00
Vance IngallsandClaude Opus 4.6 52ee81e760 feat(captions): energy-based technique selection and mandatory quality checks
- Rewrite script-to-style mapping as energy detection table
- Add mandatory animation design requirements (karaoke baseline, technique cycling)
- Simplify dynamic-techniques.md to technique selection reference
- Add transcript quality check with automatic retry rules
- Add multilingual model guidance and decision tree

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:11 +00:00
Vance IngallsandClaude Opus 4.6 4e516327ed feat(whisper): language detection, speech onset, contraction merging
- Auto-detect language and switch from .en to multilingual model when needed
- Detect speech onset in WAV to strip hallucinated words before speech begins
- Merge whisper-cpp token fragments: contractions (didn + 't → didn't),
  split capitals (C + aught → Caught), dropped-g (shin + in' → shinin')
- Interpolate zero-duration word clusters for reliable karaoke timing
- Replace non-null assertions with optional chaining in tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:25:08 +00:00
Vance Ingalls 159a2e7113 feat(skills): add dynamic caption techniques and split captions skill into references (#173)
## Summary

- Split the captions skill from a single 611-line file into focused references: `SKILL.md` (core rules), `transcript-guide.md` (whisper/transcription), `dynamic-techniques.md` (animation patterns)
- Add `audio-reactive` skill with "Content, Not Medium" constraint — steers away from generic visualizations (equalizer bars, spectrum analyzers, waveforms) toward content-grounded animation where audio drives *when* and *how much*, not *what to show*
- Add initial dynamic caption technique selection by energy level

## Test plan

- [ ] All skill files render correctly as markdown
- [ ] Cross-references between files use correct relative paths
- [ ] `audio-reactive/SKILL.md` contains the anti-pattern list and content-grounded examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-01 23:24:25 -07:00
James 870ca76c8b chore: release v0.2.1 v0.2.1 2026-04-01 21:36:24 +00:00