## Context `npx hyperframes render` fails to load assets and produces all-black video. Root causes: 1. CDN scripts (GSAP, Lottie) are left as `<script src="https://...">` in compiled HTML — the headless browser must fetch them over the network, which fails in Docker, CI, and firewalled environments 2. Assets referenced from outside the project directory (e.g. `../shared-assets/hero.png`) 404 because the file server only serves from `projectDir` 3. When GSAP fails to load, the timeline never registers, all `.clip` elements stay `visibility: hidden`, and every frame is black — with no diagnostic output 4. The linter reports `missing_gsap_script` when GSAP is bundled inline (no `<script src>` tag), which blocks users from working around the CDN issue ## What changed ### 1\. CDN script inlining (`htmlCompiler.ts`) `compileForRender` now downloads all external `<script src="https://...">` tags at compile time and inlines their content into the HTML. Rendering no longer needs network access. | Before | After | | --- | --- | | `<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>` stays in HTML, browser must fetch at runtime | Script downloaded during compilation, embedded as `<script>/* inlined: https://... */\n...code...</script>` | | Docker/CI render → `net::ERR_NAME_NOT_RESOLVED` → black video | Render works fully offline | | No feedback when CDN fails | `[Compiler] WARNING: Failed to download CDN script: ... Consider bundling it locally` | ### 2\. External asset copying (`htmlCompiler.ts`, `renderOrchestrator.ts`) After compilation, the HTML is scanned for `src`, `href`, and CSS `url()` references that resolve outside `projectDir`. These files are copied into the compiled output directory so the file server can serve them. | Before | After | | --- | --- | | `background-image: url(../shared-assets/hero.png)` → 404 (file server can't serve outside `projectDir`) | Asset detected, copied to compiled dir, path rewritten → serves correctly | | `<img src="../shared-assets/logo.png">` → 404 | Same fix — works for all `src`/`href` attributes and CSS `url()` | ### 3\. Black video diagnostics (`renderOrchestrator.ts`) When composition duration is 0 (which would produce a black video), the error now probes the browser for diagnostics instead of a generic message. | Before | After | | --- | --- | | `Invalid composition duration: 0. Check that GSAP timelines are registered.` | `Composition duration is 0 — this would produce a black video.\n\nDiagnostics:\n - GSAP is not loaded — CDN script may have failed to download. Bundle GSAP locally...\n - Browser: [Browser:PAGEERROR] gsap is not defined` | | Asset 404s during page load silently logged | `[Render] Asset load failure: ...` + `[WARN] Browser encountered network failures during page load` | ### 4\. Linter: recognize inline GSAP (`core/lint/rules/gsap.ts`) The `missing_gsap_script` rule now recognizes GSAP bundled inline — matching the producer's inlining comment (`/* inlined: ...gsap... */`), GSAP library internals (`_gsScope`, `GreenSock`), and large inline scripts (>5KB) referencing gsap. | Before | After | | --- | --- | | User inlines GSAP → linter errors with `missing_gsap_script` | Inline GSAP detected, no false error | | Producer inlines CDN → linter errors on the compiled HTML | Producer's `/* inlined: ... */` comment recognized | ## Test plan - [x] `pnpm build` passes - [x] Core tests pass (410/410, +2 new) - [x] **Reproduced baseline failures on** **`main`**: CDN scripts not inlined, external assets 404, no diagnostics - [x] **Verified fixes**: CDN script inlined, external assets copied and served, diagnostics printed - [x] Render with working CDN → `[Compiler] Inlined CDN script: ...` → render succeeds - [x] Render with broken CDN → `[Compiler] WARNING: Failed to download CDN script` + browser errors surfaced - [x] Render with assets outside project dir → `[Compiler] Found 1 asset(s) outside project directory` → assets served correctly - [x] Linter with inline GSAP → no `missing_gsap_script` false positive
Hyperframes
Write HTML. Render video. Built for agents.
Hyperframes is an open-source video rendering framework that lets you create, preview, and render HTML-based video compositions — with first-class support for AI agents via MCP.
Why Hyperframes?
- HTML-native — AI agents already speak HTML. No React required.
- Frame Adapter pattern — bring your own animation runtime (GSAP, Lottie, CSS, Three.js).
- Deterministic rendering — same input = identical output. Built for automated pipelines.
- AI-first design — not a bolted-on afterthought.
Quick Start
npx hyperframes init my-video
cd my-video
Then open the project with your AI coding agent (Claude Code, Cursor, etc.) — it has HyperFrames skills installed and knows how to create and edit compositions.
npx hyperframes preview # preview in browser (live reload)
npx hyperframes render # render to MP4
Requirements: Node.js >= 22, FFmpeg
Documentation
Full documentation at hyperframes.heygen.com — start with the Quickstart, then explore guides, concepts, API reference, and package docs.
How It Works
Define your video as HTML with data attributes:
<div id="stage" data-composition-id="my-video" data-start="0" data-width="1920" data-height="1080">
<video
id="clip-1"
data-start="0"
data-duration="5"
data-track="0"
src="intro.mp4"
muted
playsinline
></video>
<img id="overlay" data-start="2" data-duration="3" data-track="1" src="logo.png" />
<audio
id="bg-music"
data-start="0"
data-duration="9"
data-track="2"
data-volume="0.5"
src="music.wav"
></audio>
</div>
Preview instantly in the browser. Render to MP4 locally. Let AI agents compose videos using tools they already understand.
Packages
| Package | Description |
|---|---|
hyperframes |
CLI — create, preview, lint, and render compositions |
@hyperframes/core |
Types, parsers, generators, linter, runtime, frame adapters |
@hyperframes/engine |
Seekable page-to-video capture engine (Puppeteer + FFmpeg) |
@hyperframes/producer |
Full rendering pipeline (capture + encode + audio mix) |
@hyperframes/studio |
Browser-based composition editor UI |
AI Agent Skills
HyperFrames ships skills that teach AI coding agents (Claude Code, Gemini CLI, Codex, Cursor) how to write correct compositions and GSAP animations. Use these instead of writing from scratch — they encode framework-specific patterns that generic docs don't cover.
Install via CLI (recommended)
# Install all skills (HyperFrames + GSAP) — runs automatically during `hyperframes init`
npx hyperframes skills
# Or install to a specific agent
npx hyperframes skills --claude
npx hyperframes skills --cursor
Or via npx skills add
# HyperFrames skills (hyperframes-compose, hyperframes-captions)
npx skills add heygen-com/hyperframes
# GSAP skills (gsap-core, gsap-timeline, gsap-scrolltrigger, gsap-plugins, gsap-performance, gsap-utils, gsap-react, gsap-frameworks)
npx skills add greensock/gsap-skills
Installed Skills
| Source | Skills | What they teach |
|---|---|---|
| HyperFrames | hyperframes-compose, hyperframes-captions |
HTML composition structure, class="clip" rules, data-* attributes, timeline registration, rendering constraints |
| GSAP | gsap-core, gsap-timeline, gsap-performance, gsap-plugins, gsap-scrolltrigger, gsap-utils, gsap-react, gsap-frameworks |
Core API, timeline sequencing, ScrollTrigger, plugin usage, performance best practices |
In Claude Code, invoke with /hyperframes-compose, /hyperframes-captions, /gsap-core, etc.
Contributing
See CONTRIBUTING.md for guidelines on how to contribute.
License
See LICENSE for details.