Commit Graph
10 Commits
Author SHA1 Message Date
James Russo ce63160907 Merge pull request #108 from heygen-com/chore/rename-skills-namespace
chore(skills): rename compose-video/captions to hyperframes-compose/hyperframes-captions
2026-03-27 18:42:10 -07:00
JamesandClaude Opus 4.6 b8149abef5 chore(skills): rename compose-video → hyperframes-compose, captions → hyperframes-captions
Namespace skill names with `hyperframes-` prefix for clearer identity in
OSS contexts where users may have other skills installed.

Updates skill directories, SKILL.md frontmatter, CLAUDE.md, README.md,
CLI build script, init command, and project template.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 01:26:13 +00:00
Vance Ingalls 476c20747d feat: add templates (#102)
## What

Adds 4 new composition templates and fixes structural issues across all templates.

### New templates
- **decision-tree** — animated flowchart with branching paths
- **kinetic-type** — bold kinetic typography promo
- **product-promo** — multi-scene product showcase with SVG assets (3 scenes)
- **nyt-graph** — animated data chart in NYT print editorial style

### Fixes across all templates
- GSAP updated from 3.12.2 → 3.14.2 (all templates, including warm-grain, swiss-grid, vignelli, play-mode)
- New templates restructured with proper root wrapper div, `data-duration`, sub-composition refs with `data-composition-id` / `data-width` / `data-height`
- nyt-chart: replaced `${compId}` template literal variables with hardcoded `"nyt-chart"` string — cheerio's css-what parser crashes on template literals during bundling, causing silent fallback to raw HTML without runtime injection
- nyt-chart: added DOM readiness retry for dynamically created SVG elements
- kinetic-type: removed external S3 audio URL
- All templates: GSAP script loaded in `<head>` before any scripts reference it

## Why

The new templates expand the range of content types available via `hyperframes init`. The fixes ensure all templates work correctly in the studio preview (bundler inlines sub-compositions and injects the runtime).

## Test plan

- [x] All 4 new templates render in studio preview
- [x] nyt-graph chart animates bars, line, and labels on playback
- [x] Existing templates unaffected (GSAP version bump is backwards compatible)
- [x] `hyperframes lint` passes on all templates
- [x] `generators.ts` updated with new template IDs
2026-03-27 17:31:28 -07:00
James fff87300f1 fix(cli): point agents to docs CLI and llms.txt instead of guessing URLs
The shared CLAUDE.md in scaffolded projects mentioned
hyperframes.heygen.com alongside doc topic names, causing AI agents
to guess incorrect URLs like /compositions instead of using the local
`hyperframes docs` CLI command or the correct /concepts/compositions
path. Now explicitly directs agents to use the CLI for quick reference
and llms.txt for full doc URL discovery.
2026-03-27 22:22:47 +00:00
JamesandClaude Opus 4.6 42c79f3bd3 feat(cli): scaffold CLAUDE.md and project-level skills into init
New HyperFrames projects created via `hyperframes init` now include:

- CLAUDE.md + AGENTS.md — teaches AI agents about skills, commands,
  project structure, and framework rules (class="clip", timeline
  registration, determinism). Agents know to invoke /compose-video
  before writing compositions.
- .claude/skills/{compose-video,captions} — project-level skills for
  immediate availability in the current agent session (global skills
  require a session restart to discover).
- Updated next-steps output with `hyperframes docs <topic>` and a
  link to hyperframes.heygen.com.
- Updated README with "AI Agent Skills" section documenting
  `npx hyperframes skills` and `npx skills add` install paths.
- Repo-level CLAUDE.md for framework contributors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:15:54 +00:00
Miguel ÁngelandClaude Opus 4.6 d52ea88df5 fix(cli): make blank template a full HTML document
The blank template was a bare `<div>` fragment without `<!DOCTYPE>`,
`<head>`, or `<body>`. This caused:
- Blank preview (bundler/runtime can't initialize from a fragment)
- "Failed to run lint" (parsing errors on the malformed document)

All other templates (swiss-grid, vignelli, warm-grain, play-mode) are
proper HTML documents — blank was the only outlier.

Also improves lint error reporting to show the actual error message
instead of the generic "Failed to run lint."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:50:53 -04:00
JamesandClaude Opus 4.6 2280273f79 fix(cli): remove empty src attrs from swiss-grid audio elements
Empty src="" on <audio> elements causes the browser to fetch the
current page URL as the audio source, producing 404 errors in the
console during rendering. These are placeholder sound effect slots
whose src should be set dynamically when audio is configured.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:06:00 +00:00
Vance IngallsandClaude Opus 4.6 f4367d5726 feat(cli): add whisper transcription and template improvements (#53)
* feat(cli): add whisper transcription to init flow

New modules:
- whisper/manager.ts: download/cache whisper.cpp binary + model
  (~/.cache/hyperframes/whisper/)
- whisper/transcribe.ts: extract audio, run whisper, save transcript.json

Init flow changes:
- "Got a video or audio file?" now accepts audio-only files (mp3, wav, m4a)
- "Generate captions from audio?" prompt after file selection
- Transcription produces transcript.json in project root
- Graceful fallback if whisper/ffmpeg unavailable

Supports: macOS ARM64/x86, Linux x86_64. Downloads whisper.cpp v1.7.3
from GitHub releases and ggml-base.en model from Hugging Face.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use brew/system whisper instead of downloading binaries

whisper.cpp doesn't ship pre-built macOS/Linux CLI binaries.
Use brew install whisper-cpp on macOS (auto-installs if brew available),
system PATH lookup otherwise. Model still downloaded from Hugging Face.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): simplify whisper install — detect or instruct, don't build

Remove build-from-source complexity. If whisper-cpp is found on PATH,
use it. If not, show install instructions instead of blocking:

  "To generate captions, install whisper-cpp: brew install whisper-cpp"

The transcription prompt only appears when whisper is available.
When it's not, the user sees the install command and can re-run init.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(cli): auto-install whisper via brew or build from source

ensureWhisper() now tries 4 strategies in order:
1. System PATH (whisper-cli or whisper already installed)
2. Homebrew (macOS: brew install whisper-cpp)
3. Build from source (git clone + cmake, ~30-60s)
4. Show install instructions as last resort

Init flow always asks "Generate captions?" — whisper is installed
automatically in the background if needed. No user intervention
required on macOS with Xcode CLI tools or any system with git+cmake.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add window.__timelines guard to all templates

The studio bundler doesn't always initialize window.__timelines
before template scripts run, causing "Cannot set properties of
undefined" errors. Add defensive guard to every template.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(cli): patch template captions with actual transcript data

After scaffolding, if transcript.json exists, replace the hardcoded
word array in the template's captions composition with the real
transcript data. The template's caption animation and styling are
preserved — only the word data changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): show install notice when whisper needs to be installed

When whisper-cpp isn't found, show an info message before the spinner:
"whisper-cpp not found — installing automatically..."
Then the spinner shows "Installing whisper-cpp (this may take a moment)..."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add muted and playsinline to all template video elements

The framework requires video elements to have muted and playsinline
attributes. All four templates were missing these, causing video
to not play in the studio preview.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): flat asset structure + separate audio tracks in templates

Assets: video, images, fonts all go at project root (not assets/ or
fonts/ subdirectories). The studio preview can't resolve relative
paths from subdirectories due to the /preview URL suffix.

Audio: added <audio> elements alongside muted <video> in all 4
templates so the video's audio plays back. The framework requires
muted video + separate audio element.

Removed assets/ and fonts/ directory creation from scaffoldProject.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(studio): inject base tag for asset resolution in preview

The preview iframe serves bundled HTML from /api/projects/:id/preview
but relative asset paths (video.mp4, font.woff2) resolve to the wrong
URL without a <base> tag. Now injects <base href="/api/projects/:id/preview/">
so relative paths route through the static asset handler.

Also adds proper MIME types for video, audio, image, and font files
served from the preview asset route.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(studio): serve HyperFrames runtime in dev mode

The preview runtime script had an empty src — the framework never
loaded, so video playback and clip lifecycle didn't work.

Now auto-detects packages/cli/dist/hyperframe-runtime.js and serves
it at /api/runtime.js. No env var needed in dev mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): filter whisper special tokens from transcript

Use --output-json instead of --output-json-full to avoid special
tokens like [_TT_485] and [BLANK_AUDIO]. Also filter remaining
bracket tokens when building the word array for captions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use --output-json-full for word-level timestamps

--output-json only produces segment-level timing (no tokens).
--output-json-full is required for word-level timestamps that
the captions template needs. Special tokens are filtered out
by the patchTranscript function.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(cli): patch template durations to match uploaded video

Templates now use __VIDEO_DURATION__ placeholder that gets replaced
with the actual probed video duration. All data-duration values on
the root composition, video, audio, and caption clips are updated.

Without a video, defaults to 10 seconds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): merge punctuation tokens with preceding word

Whisper outputs punctuation (. , ! ?) as separate tokens. These
appeared as standalone words in captions, sometimes in the wrong
group. Now merged with the preceding word during transcript
normalization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): match both TRANSCRIPT and script variable names in templates

Three templates use `const TRANSCRIPT = [...]` while warm-grain uses
`const script = [...]`. The patchTranscript function now matches both.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): security and template fixes

- Replace shell injection risk (execSync rm) with unlinkSync in transcribe.ts
- Add GIT_TERMINAL_PROMPT=0 to whisper buildFromSource git clone
- Fix hardcoded data-duration="18" in warm-grain captions template
- Add data-start="0" to root compositions in swiss-grid, vignelli, warm-grain
- Add data-start="0" to warm-grain grain-overlay composition
- Deduplicate hasFFmpeg: remove from init.ts, import from whisper/manager.ts
- Add my-video/ and packages/studio/data/ to .gitignore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): format warm-grain captions and fix TS nullability errors

- Format warm-grain/compositions/captions.html
- Add optional chaining on token.offsets (may be undefined)
- Use intermediate variable for lastWord to satisfy TS strict checks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(cli): add blank template option, smart defaults for video vs audio

- Blank template: minimal scaffolding (root composition, video, audio,
  GSAP timeline) with __VIDEO_SRC__ and __VIDEO_DURATION__ placeholders
- Template defaults: video uploads default to "blank" (user brings
  their own content), audio-only defaults to "warm-grain" (motion
  graphics template since there's no video to show)
- Audio-only projects now tracked with isAudioOnly flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): address whisper review feedback

- Clean stale builds: if BUILD_DIR exists but no binary, nuke and retry
- Build failures clean up BUILD_DIR so next attempt starts fresh
- patchTranscript regex scoped within <script> blocks to prevent
  matching across block boundaries
- Removed hardcoded model size hint (~148MB)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add missing rmSync import to whisper manager

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove test project and lock file

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): address review items 7-12 — execFileSync, build diagnostics, WAV verification

- manager.ts: replace all execSync with execFileSync to prevent command injection
- manager.ts: capture cmake stderr and include in build failure error message
- transcribe.ts: verify WAV is 16kHz mono via ffprobe before passing to whisper
- init.ts: replace fragile JSON formatting with JSON.stringify(words, null, 2)
- init.ts: fix default duration from "10" to "5" matching DEFAULT_META
- init.ts: add probeAudioDuration() and --audio/--skip-transcribe flags
- init.ts: extract finalizeProject() to reduce code path duplication
- init.ts: wire transcription into non-interactive path

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:05:15 -07:00
Vance Ingalls 20be2ea1c2 style: apply oxfmt baseline formatting across all source files (#25)
## Summary
- Run `oxfmt .` across the entire codebase to establish formatted baseline
- 299 files changed — mechanical formatting only, no logic changes
- Double quotes, semicolons, 2-space indent, trailing commas, 100 print width

Part 3/4 of [VA-851](https://linear.app/heygen/issue/VA-851/pre-migration-configure-eslint-prettier-and-conventional-commits)

## Test plan
- [x] `pnpm format:check` — all 426 files pass
- [x] `pnpm -r typecheck` — all packages pass
- [x] `pnpm build` — all packages build
- [x] All 348 tests pass
2026-03-23 17:15:14 -07:00
Vance IngallsandClaude Opus 4.6 9f8e5ba5a1 initial code (#2)
* feat: initial code port from hyperframes-internal

Port all OSS-ready packages from the internal monorepo:
- @hyperframes/core — shared types, HTML generation, GSAP utilities, runtime
- @hyperframes/cli — CLI for creating, previewing, and rendering compositions
- @hyperframes/engine — framework-agnostic rendering engine (BeginFrame + FFmpeg)
- @hyperframes/producer — video rendering pipeline (Puppeteer + FFmpeg)
- @hyperframes/ui-player — browser-based video player component
- @hyperframes/studio — composition editor (React frontend + Hono backend)

Includes regression test suite with Docker-based test harness.

All HeyGen-internal references, deployment infrastructure, and
proprietary assets have been removed. Package names migrated
from @app/* to @hyperframes/*.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: scrub internal codenames and stale references from OSS port

- Replace static.heygen.ai runtime URLs in test fixtures
- Remove internal CDN publish script (publish-hyperframe-runtime.ts)
- Replace sandbox-studio, sandbox-interceptor, __magicEditRuntime
  with neutral names (studio, hyperframe-runtime, __hyperframeRuntime)
- Fix stale Vault API / localhost references in docs
- Remove broken deprecated_studio link

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove remaining internal codenames and stale references

- Delete stale producer README.md and PIPELINE.md (referenced nonexistent files)
- Replace "Cerberus" codename with "HyperFrames" in test design reviews
- Replace magic-edit postMessage identifiers with hf-preview/hf-parent
- Rename debug-magic-edit-timeline.ts to debug-timeline.ts
- Replace "Motion Cut" with "HyperFrames" in Timeline comments
- Fix studio/CLI references to nonexistent archive package
  (use local data/projects/ dir, stub render proxy)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:43:56 -07:00