- name
- hyperframes-helper
- description
- Build agent-friendly motion-graphics videos with Hyperframes (HTML-to-MP4). Three levels of effort — Level 1 website-to-video for quick conversions, Level 2 storyboards for guided design iteration, Level 3 fully custom guided-video productions with cut/storyboard/motion-graphics workflow. Triggers on "hyperframes", "html to mp4", "render with hyperframes", "motion graphics for [recording]", "storyboard a video", "/hyperframes-helper".
# Hyperframes Helper
A practical kit for building motion-graphics videos with Hyperframes — HeyGen's open-source HTML-to-MP4 renderer. Three levels of effort matched to three different goals.
## What is Hyperframes
Hyperframes is an open-source video composition framework. You write HTML/CSS/GSAP, it renders to a deterministic MP4. The output looks like motion graphics; the source is just a webpage. That makes it agent-native — LLMs can write it first try, no React/Remotion bundler dance.
- **GitHub:** https://github.com/heygen-com/hyperframes
- **Docs:** https://hyperframes.heygen.com
- **License:** Apache 2.0 — free, fully local, no HeyGen API key needed
## Install Hyperframes
You only need Node.js. Hyperframes runs via `npx`:
```bash
# Verify Node is available
node --version
# See what Hyperframes can do
npx hyperframes@latest --help
# Scaffold a new project
npx hyperframes@latest init my-video
cd my-video
# Add the official agent skills (gives you /hyperframes, /gsap, /website-to-hyperframes)
npx skills add heygen-com/hyperframes
# Open Studio (live preview at http://localhost:3002)
npx hyperframes@latest preview
# Lint your composition
npx hyperframes@latest lint
# Render to MP4
npx hyperframes@latest render -o output.mp4 --fps 30
```
First render downloads Chrome (~101 MB), one-time. Cached after that.
This kit ships **on top of** Hyperframes — it's a layer of patterns, templates, and recipes you reach for once you've decided which Level you're working at.
---
## The Three Levels
The complexity floor depends on what you want. Pick the level that matches.
---
### Level 1 · Website-to-Video
Fastest path. You already have a webpage / component / animated CSS — turn it into an MP4.
**When to use:**
- You found a beautiful animated component on the web and want a 6-second loop
- You have a brand site and want a 15-second hero animation as a video file
- You want a quick capture of an interactive demo
**How:**
```bash
# In your Hyperframes project
/website-to-hyperframes
```
The official Hyperframes website-to-video skill handles this end to end. It captures the page, wraps it as a Hyperframes composition, and renders. Read more in the [Hyperframes docs](https://hyperframes.heygen.com).
**Where to find good source HTML:**
- **[21st.dev](https://21st.dev)** — high-quality React component examples. Many work great as Hyperframes scenes — strip the React wrapper, keep the HTML/CSS/animations.
- **[CodePen](https://codepen.io)** — search for "shader", "particles", "loader" — lots of self-contained animated CSS pens.
- **Hyperframes registry** — `npx hyperframes@latest catalog` shows blocks/components shipped with Hyperframes itself.
**Output:** a single MP4, deterministic, captured at the fps you choose.
---
### Level 2 · Storyboards
You're producing original motion graphics from scratch and want to iterate on the layout BEFORE committing to a real composition. Iterating in Studio costs ~15 min per cycle. Iterating on a storyboard HTML costs ~1 min.
**When to use:**
- Original motion-graphics video (intro, hook, ad, lesson trailer)
- You have a brief but no clear shot list yet
- You want to share a visual plan before writing GSAP
**How:**
1. Copy `templates/storyboard-template.html` into your project as `storyboard.html`
2. Fill in scene cards: scaled 1920×1080 layout previews + motion notes per scene
3. Open in browser, share the path with your reviewer
4. Iterate in HTML — drag elements around the preview boxes, rewrite motion notes
5. Once locked, only THEN move to the real composition
**The storyboard template ships with:**
- Header with title + meta pills + horizontal proportional timeline bar
- Sticky table of contents for nav
- Scene cards (two-pane: scaled layout preview + notes panel)
- Pre-styled placeholder elements: video frame, text panels, sample cards, watermark, motion arrows
- Same typography + color tokens as the composition template
**Mark-up methods your reviewer can use:**
- Open the file, add `<!-- COMMENT: ... -->` tags inline
- Screenshot the page and draw arrows
- Just describe in chat: "scene 3 should X"
**Why this saves time:** every storyboard iteration that catches a layout mistake saves you a 15-minute compose-lint-preview cycle. Five storyboard rounds = one composition round.
---
### Level 3 · Guided Videos
Fully custom production with a real camera recording at the centre. The full RoboNuggets pipeline — three steps:
```
┌──────────────┐ ┌─────────────────┐ ┌───────────────────┐
│ STEP 01 │ ─→ │ STEP 02 │ ─→ │ STEP 03 │
│ Cut the │ │ Storyboard the │ │ Add in motion │
│ Video │ │ Title Cards │ │ graphics │
└──────────────┘ └─────────────────┘ └───────────────────┘
```
**When to use:**
- Talking-head intros and outros
- Lesson openers where you appear on camera
- Any video where you're cutting a real recording AND adding motion graphics on top
#### Step 01 · Cut the Video
Two passes — silence cut, then retake cut. Both use ffmpeg.
**Pass A — silence cut** (`templates/silence-cut.sh`)
```bash
ffmpeg -i input.mkv -af "silencedetect=noise=-30dB:d=0.4" -f null - 2>&1 | grep silence
```
This prints all silence regions. Build keep-ranges with a 0.04s pad on each side, then re-encode with tight 1s GOP keyframes (Hyperframes-ready). Template includes the full `filter_complex trim/atrim/concat` skeleton.
**Pass B — transcribe** (`templates/transcribe-whisper.py`)
```bash
pip install faster-whisper
python templates/transcribe-whisper.py input_silence_cut.mp4
```
Outputs `*.transcript.json` + `*.transcript.txt` with word-level timestamps.
> Why faster-whisper instead of WhisperX: torchaudio is fragile on Windows (libtorchaudio load errors). faster-whisper uses CTranslate2 — no torch dependency.
**Pass C — retake cut** (`templates/cut-retakes.py`)
Identify retake clusters from the word-level transcript. Apply the **last-take rule**: when a phrase is repeated, keep only the LAST take and cut everything before it (false starts, earlier attempts, "let me start over" markers). Drop your `KEEPS` ranges into the script and run.
**Alternative tool:** if you'd rather skip the manual pass, [video-use](https://github.com/browser-use/video-use) is an automated video-editing agent that can cut filler words and false starts. Slower per run, fewer fine-tuning hooks, but zero scripting required.
**Tip:** ship a `script-review.html` — a side-by-side of "current script vs proposed clean script" with retakes struck through in red, last-takes highlighted in green, and a numbered cut table (range, duration, what it removes, why). Lets reviewers approve cuts before any re-encode.
#### Step 02 · Storyboard the Title Cards
This is Level 2, applied inside the bigger pipeline. Use `templates/storyboard-template.html` to plan the title cards / overlay scenes that will sit on top of your cut video.
**Common title-card patterns:**
- **Floating cards** on one side of the screen (right or left), one per spoken beat, paced to the transcript
- **Centred big text** for major moments — "*major* upgrade", "*open source*", "*free & open source*"
- **Animated highlights** (curved underlines, glowing words, pulsing borders)
- **Brand corner pills** (status pill top-left, counter top-right, brand pill bottom-left)
See `templates/recipes.md` for copy-paste implementations.
#### Step 03 · Add in Motion Graphics
Centre stage motion graphics that appear at specific beats. Common shapes:
- **Shader flashes** — Three.js fragment shader as a 0.5–1s transition flourish
- **Wireframe globe** — D3 `geoOrthographic` with country outlines + halftone dots, on a transparent canvas
- **Chroma-keyed character** — 3D rendered icon flip on green-screen, keyed out via SVG `feColorMatrix` filter
- **Logo assemblies** — segments fade-in stagger, then breathe loop
- **Big closing text + icons** — final tagline with a row of brand marks
Each pattern has a copy-paste recipe in `templates/recipes.md`.
**Composition tip:** start each motion graphic centred on canvas, then animate it sliding to one side as a label fades in on the other. Three sequential motion graphics tell a story without crowding.
---
## Critical Framework Rules (lint gotchas)
These are non-negotiable — every one corresponds to a Hyperframes lint error you WILL hit if you skip:
1. **Every timed element needs `class="clip"` + `data-start` + `data-duration` + `data-track-index`.** No exceptions.
2. **GSAP must NOT animate clip elements.** The framework manages clip visibility. Animating opacity/visibility on a `class="clip"` div = `gsap_animates_clip_element` error. Fix: wrap each scene in an outer clip-shell + inner animatable div.
3. **Clips on the same track CANNOT overlap (even by 0.001s).** Floating-point precision bites — `start=23.85, duration=4.55` ends at `28.400000002`, collides with `start=28.40`. Either bump duration to `4.54` or move to a different track.
4. **Visually-overlapping elements need separate tracks.** Four sample cards visible together → tracks 12, 13, 14, 15 (one each).
5. **GSAP timeline must be paused + registered.**
```js
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
// ... tl.from(...) ...
window.__timelines["main"] = tl; // matches data-composition-id
```
6. **Deterministic logic only.** No `Math.random()`, no `Date.now()`, no `fetch()`. Render is frame-by-frame seek.
7. **Video uses `muted` + separate `<audio>` element.** Playing audio through the `<video>` tag breaks frame seek.
8. **Source video needs tight keyframes (1s GOP).**
```bash
ffmpeg -i in.mp4 -c:v libx264 -preset fast -crf 18 \
-r 30 -g 30 -keyint_min 30 \
-force_key_frames "expr:gte(t,n_forced*1)" \
-c:a aac -b:a 192k -movflags +faststart out.mp4
```
9. **Canvas-based animations must redraw on timeline tick.** Don't use `requestAnimationFrame`. Use `tl.eventCallback('onUpdate', () => drawCanvas(tl.time()))`.
10. **`hard kill` not strictly required for clip elements.** Framework hard-cuts at clip end. Don't `tl.set(..., {visibility: hidden})` on clip elements.
11. **`repeat: -1` (infinite) is FORBIDDEN.** Lint error: `gsap_infinite_repeat`. Use a finite count derived from the hold duration:
```js
const HOLD = 6.0, CYCLE = 1.6;
const repeats = Math.max(0, Math.floor(HOLD / CYCLE) - 1);
tl.to('.element', { ..., repeat: repeats, yoyo: true });
```
12. **Multiple `<audio>` elements with the same `src` cause echo.** The framework gates clip *visibility* but several preloaded audio elements still play simultaneously in Studio preview. Use ONE `<audio>` clip pointing to a pre-cut clean audio file.
13. **Pseudo-elements (`::before` / `::after`) cannot be GSAP'd.** Replace with real DOM child divs.
14. **Studio's auto-assigned inline `style="z-index: N"` may be inverted.** If hex bg or vignette appears on top of video after Studio edits, bulk-strip inline z-indexes:
```python
import re
s = open('index.html').read()
out = re.sub(r' style="z-index: \d+"', '', s)
open('index.html', 'w').write(out)
```
15. **Stacking context gotcha for the contracted-video frame.** If `#videoFrame { z-index: 2 }`, sibling float-text without z-index gets buried below it. Either give the floats explicit `z-index ≥ 2`, OR remove videoFrame's z-index and place behind-elements (like a shader) BEFORE videoFrame in DOM.
16. **`z-index: -1` traps an element behind the body's background.** When `body { background: #000 }`, a `z-index: -1` element renders BEHIND the body paint and disappears. Use DOM ordering instead — place the "behind" element earlier in the DOM, no z-index.
## Multi-clip cut-editing pattern (Studio-draggable cuts)
Hyperframes Studio explicitly **cannot split a clip mid-source** ([per the docs](https://hyperframes.heygen.com/guides/timeline-editing)). The workaround:
Keep the uncut source on disk, then define multiple `<video>` clips on the timeline, each with a different `data-media-start`. Drag the LEFT handle of any clip in Studio to fine-tune that segment's cut boundary live — no ffmpeg re-run.
```html
<div id="videoFrame">
<video class="stage-video clip" data-start="0.00" data-duration="2.56"
data-media-start="2.24" data-track-index="2" muted playsinline preload="auto"
src="assets/source-uncut.mp4"></video>
<video class="stage-video clip" data-start="2.56" data-duration="3.74"
data-media-start="9.12" data-track-index="3" muted playsinline preload="auto"
src="assets/source-uncut.mp4"></video>
<!-- alternate tracks 2/3 so adjacent clips don't collide on a shared track -->
</div>
```
Trade-off: audio CANNOT be split this way (rule 12 — echo). Pre-cut a single clean audio file via `cut-retakes.py` and use ONE `<audio>` clip. When you drag video boundaries in Studio, you'll need to re-cut the audio to keep sync.
For one-shot delivery with no Studio drag-editing needed, use a single ffmpeg-cut `source.mp4` + single `<audio>` `source.mp4` — simpler.
## Studio editing limits (per official docs)
Studio supports only:
- ✅ Drag clip horizontally → updates `data-start`
- ✅ Drag clip between rows → updates `data-track-index`
- ✅ Drag right handle → updates `data-duration` (end-trim)
- ✅ Drag LEFT handle on **media** clips → updates `data-start` + `data-media-start` (front-trim into source)
- ✅ Reorder rows vertically → updates inline `z-index`
- ❌ Splitting / cutting clips mid-source
- ❌ Front-trim on non-media (motion) clips
- ❌ Keyboard shortcuts
- ❌ Multi-select
- ❌ Undo / redo
Source: https://hyperframes.heygen.com/guides/timeline-editing
## Rendering at highest quality
```bash
cd [project] && npx hyperframes@latest render \
-o renders/final.mp4 \
--fps 30 --quality high --crf 16 --gpu
```
- `--quality high` — top quality tier
- `--crf 16` — near visually-lossless (lower = bigger file, higher quality; standard is 18-23)
- `--gpu` — GPU encoding
- Render time on 16-core: ~2.5–3 min for a 30s composition with video + GSAP
Two renders can run in parallel — Hyperframes spawns 5–6 worker Chrome processes per render anyway, so two renders share well.
## Recipes
`templates/recipes.md` ships 10 copy-paste patterns. Reach for them once you've got the basics:
1. **Liquid glass card** — frosted iOS-style backdrop blur with sheen and refraction
2. **Pulse border** — single-color rotating gradient on the card edge
3. **White-glow text** — multi-layer text-shadow for readability over video
4. **Curved underline** — animated SVG curve beneath an em highlight
5. **Chroma key** — green-screen knockout via SVG `feColorMatrix`
6. **Multi-clip cut-editing** — the data-media-start pattern above
7. **Pulsing rings** — concentric outward pulse around a logo
8. **Corner notes** — status / counter / brand pill chrome
9. **D3 globe** — wireframe earth with halftone dots, transparent canvas
10. **Pixel-art icon row** — sample row of small character icons (8×8 pixel grid)
## Files in this kit
```
hyperframes-helper/
├── SKILL.md ← this file
└── templates/
├── composition-template.html ← scaffold: tokens, hex mesh, GSAP, watermark
├── storyboard-template.html ← Level 2 storyboard, 5-scene starter
├── recipes.md ← copy-paste pattern library (10 recipes)
├── silence-cut.sh ← Step 01 / Pass A: ffmpeg silence trim
├── transcribe-whisper.py ← Step 01 / Pass B: faster-whisper transcript
└── cut-retakes.py ← Step 01 / Pass <your-project-path> last-take-rule retake removal
```
Ver en GitHub