Merge pull request #1976 from heygen-com/docs-audit-fixes

docs: fix 53 inaccuracies across all documentation
This commit is contained in:
Ular Kimsanov
2026-07-05 21:34:05 -07:00
committed by GitHub
23 changed files with 111 additions and 121 deletions
+2 -2
View File
@@ -10,8 +10,8 @@ Hyperframes uses HTML data attributes to control timing, media playback, and [co
| Attribute | Example | Description |
|-----------|---------|-------------|
| `data-start` | `"0"` or `"intro"` | Start time in seconds, or a clip ID reference for [relative timing](#relative-timing) |
| `data-duration` | `"5"` | Duration in seconds. Required for images. Optional for video/audio (defaults to source duration). On the **root** composition it sets the total render length (see [Composition Attributes](#composition-attributes)); on nested sub-compositions it is ignored (their length comes from their child timeline). |
| `data-track-index` | `"0"` | Timeline track number. Controls z-ordering (higher = in front) and groups clips into rows. Clips on the same track cannot overlap. |
| `data-duration` | `"5"` | Duration in seconds. Required for images and sub-compositions. Optional for video/audio (defaults to source duration). On the **root** composition it sets the total render length (see [Composition Attributes](#composition-attributes)). |
| `data-track-index` | `"0"` | Timeline track number. Temporal ordering — groups clips into rows on the timeline. Clips on the same track cannot overlap. Does **not** control z-ordering (use CSS `z-index` for that). |
## Media Attributes
+1 -1
View File
@@ -14,7 +14,7 @@ The rendering pipeline is frame-by-frame and seek-driven. No realtime playback i
The [engine](/packages/engine) computes the time for each frame using integer math: `time = floor(frame) / fps`. There is no wall-clock dependency -- rendering is entirely decoupled from real time.
</Step>
<Step title="Seek">
The [frame adapter](/concepts/frame-adapters) receives a `seekFrame(frame)` call and deterministically positions all animations, DOM state, and canvas content to the exact frame. The adapter's `renderSeek` pauses all [GSAP](/guides/gsap-animation) timelines and seeks them to the computed time.
The [frame adapter](/concepts/frame-adapters) receives a `seekFrame(frame)` call and deterministically positions all animations, DOM state, and canvas content to the exact frame. The adapter pauses all [GSAP](/guides/gsap-animation) timelines and seeks them to the computed time.
</Step>
<Step title="Capture">
Chrome's `HeadlessExperimental.beginFrame` API captures the pixel buffer for the current frame. This is a single, atomic operation -- no partial paints or race conditions.
+1
View File
@@ -116,6 +116,7 @@ All runtime adapters live in the `/hyperframes-animation` skill — invoke it fo
| Lottie / dotLottie | `goToAndStop(timeMs, false)`, raw-frame setters, or player seek APIs | `/hyperframes-animation` |
| Three.js / WebGL | `hf-seek` events plus `window.__hfThreeTime` for deterministic scene rendering | `/hyperframes-animation` |
| Web Animations API | `document.getAnimations()` and `animation.currentTime` | `/hyperframes-animation` |
| TypeGPU / WebGPU | GPU compute shaders with deterministic seek via `hf-seek` events | `/hyperframes-animation` |
Community adapters are welcome -- if it can seek by frame, it belongs in Hyperframes.
+1 -1
View File
@@ -44,7 +44,7 @@ The Lambda handler is a thin dispatch: parse the Step Functions event, download
| Tool | Why | Install |
|------|-----|---------|
| AWS credentials | The CLI and the deploy step both call AWS APIs. | Env vars, `~/.aws/credentials`, SSO, or IMDS — any chain `boto3` would resolve. |
| AWS credentials | The CLI and the deploy step both call AWS APIs. | Env vars, `~/.aws/credentials`, SSO, or IMDS — any chain the AWS SDK for JavaScript v3 would resolve. |
| AWS SAM CLI | `hyperframes lambda deploy/destroy` shells out to `sam deploy`/`sam delete`. | [Install guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) |
| `bun` | Used to build `packages/aws-lambda/dist/handler.zip` at deploy time. | `npm install -g bun` or [bun.sh](https://bun.sh) |
| HyperFrames repo checkout | `lambda deploy` builds the Lambda handler ZIP from source. Adopters who deploy outside a checkout can set `HYPERFRAMES_REPO_ROOT` to point at one. | `git clone https://github.com/heygen-com/hyperframes` |
+2 -2
View File
@@ -44,7 +44,7 @@ gcloud builds submit . \
--tag us-central1-docker.pkg.dev/PROJECT/hyperframes/hyperframes-render:v1
# 2. Apply the module.
cd node_modules/@hyperframes/gcp-cloud-run/terraform
cd packages/gcp-cloud-run/terraform
terraform init
terraform apply \
-var project_id=PROJECT \
@@ -96,4 +96,4 @@ examples/gcp-cloud-run/scripts/smoke.sh --project my-project --region us-central
## Supported formats
Same as the distributed pipeline everywhere: `mp4` (H.264 / H.265), `mov` (ProRes), `webm` (VP9), and `png-sequence`. HDR mp4 is not supported in distributed mode.
Same as the distributed pipeline everywhere: `mp4` (H.264 / H.265), `webm` (VP9), `mov` (ProRes), and `png-sequence`. HDR mp4 is not supported in distributed mode.
+2
View File
@@ -58,8 +58,10 @@ Hyperframes renders to 4K (3840×2160) two ways. Both produce a true 4K MP4; pic
|--------|-----------|---------|
| `landscape` | 1920×1080 | `1080p`, `hd` |
| `portrait` | 1080×1920 | `1080p-portrait` |
| `square` | 1080×1080 | `1080p-square`, `square-1080p` |
| `landscape-4k` | 3840×2160 | `4k`, `uhd` |
| `portrait-4k` | 2160×3840 | `4k-portrait` |
| `square-4k` | 2160×2160 | `4k-square` |
Examples:
+1 -1
View File
@@ -48,7 +48,7 @@ Include GSAP and create a paused timeline:
## Supported Properties
`opacity`, `x`, `y`, `scale`, `scaleX`, `scaleY`, `rotation`, `width`, `height`, `visibility`, `color`, `backgroundColor`, and any CSS-animatable property.
`opacity`, `x`, `y`, `scale`, `scaleX`, `scaleY`, `rotation`, `color`, `backgroundColor`, and other CSS-animatable transform/color properties. Do **not** animate `visibility`, `width`, or `height` — these break deterministic rendering.
## Timeline Duration and Composition Duration
+1 -1
View File
@@ -21,7 +21,7 @@ When you open a composition in Studio, the timeline shows **diamond markers** on
Select any animated element in the preview or timeline to open the Design Panel. The **Animation** section shows:
- **Method badge** — `Animate`, `Animate In`, or `Animate Out` (maps to `.to()`, `.from()`, `.fromTo()`)
- **Method badge** — `Animate`, `Animate In`, or `From → To` (maps to `.to()`, `.from()`, `.fromTo()`)
- **Timing** — Length (duration) and Starts at (position on timeline)
- **Speed** — The GSAP ease (e.g., `power2.inOut`, `back.out(3)`)
- **Speed curve** — Visual preview of the easing function
+27 -28
View File
@@ -1,6 +1,6 @@
---
title: The Pipeline
description: "The 7-step pipeline for producing any Hyperframes video: capture, design, script, storyboard, voiceover, build, validate."
description: "The 7-step pipeline for producing any Hyperframes video: capture, design, strategy & messaging, storyboard + script, voiceover, build, validate."
---
Every well-structured Hyperframes video flows through the same 7 steps, whether it starts from a website, a PDF, a CSV, or a blank page. Each step produces a named artifact that the next step depends on, so your AI agent (and you) always know what's done, what's next, and where the creative decisions live on disk.
@@ -11,15 +11,15 @@ This pipeline is the backbone of the [website-to-video workflow](/guides/website
Each step produces an artifact that feeds the next:
| # | Step | Output | What happens |
|---|---------------|-----------------------------------------|-------------------------------------------------------------------------|
| 1 | **Capture** | `capture/` | Extract screenshots, design tokens, fonts, assets, animations from a source |
| 2 | **Design** | `DESIGN.md` | Brand reference: colors, typography, components, do's and don'ts |
| 3 | **Script** | `SCRIPT.md` | Narration text with hook, story, proof, and CTA |
| 4 | **Storyboard**| `STORYBOARD.md` | Per-beat creative direction: mood, assets, animations, transitions |
| 5 | **VO + Timing**| `narration.wav` + `transcript.json` | TTS audio with word-level timestamps |
| 6 | **Build** | `compositions/*.html` | Animated HTML compositions, one per beat |
| 7 | **Validate** | Snapshot PNGs + `lint`/`validate` pass | Visual verification and runtime checks before delivery |
| # | Step | Output | What happens |
|---|-------------------------|-----------------------------------------|-------------------------------------------------------------------------|
| 1 | **Capture** | `capture/` | Extract screenshots, design tokens, fonts, assets, animations from a source |
| 2 | **Design** | `DESIGN.md` | Brand reference: colors, typography, component stylings, spacing, iteration guide |
| 3 | **Strategy & Messaging**| — | Align on video type, style, the ONE message, narrative arc, and audience |
| 4 | **Storyboard + Script** | `STORYBOARD.md` + `SCRIPT.md` | Concept-first storyboard and narration script, written together |
| 5 | **VO + Timing** | `narration.wav` + `transcript.json` | TTS audio with word-level timestamps |
| 6 | **Build** | `compositions/*.html` | Animated HTML compositions, one per beat |
| 7 | **Validate** | Snapshot PNGs + `lint`/`validate` pass | Visual verification and runtime checks before delivery |
<Tip>
Not every project uses every step. A no-narration brand reel skips Step 5; a hand-authored composition skips Steps 1-2. But the order matters: scene durations come from narration, animation choices come from the storyboard, and the storyboard depends on the design reference. Skip a step only when you don't need its artifact downstream.
@@ -76,36 +76,35 @@ For sources that aren't websites (PDFs, decks, CSVs, notes), capture isn't a lit
`DESIGN.md` is the brand cheat sheet. It encodes the visual identity factually so every downstream decision can reference exact colors, fonts, and components instead of inventing them. It's a reference document, not a creative plan. The creative work happens in the storyboard.
A typical `DESIGN.md` has six sections:
A typical `DESIGN.md` has five sections:
| Section | What it captures |
|---------|------------------|
| **Overview** | 3-4 sentences describing layout patterns, color strategy, typography tone |
| **Colors** | 5-10 HEX values with semantic roles (primary surface, accent warm, etc.) |
| **Typography** | Font families with weights, roles, and distinctive usage |
| **Components** | Patterns the brand uses: bento grids, logo walls, gradient meshes |
| **Imagery** | Asset categories and how the brand uses them |
| **Do's and Don'ts** | Hard rules: "white backgrounds, never dark", "no drop shadows" |
| **Visual Theme** | 3-5 sentences describing the brand's visual personality — dark/light, contrast, mood, what makes it distinctive |
| **Quick Reference** | Colors (8-12 HEX values with semantic roles and WCAG contrast ratios) and fonts (families, weights, roles, file paths) |
| **Component Stylings** | Exact CSS-level specs for 6-12 components the brand uses: buttons, cards, containers, distinctive UI patterns |
| **Spacing & Layout** | Base spacing unit, scale with usage, max-width / grid, and breakpoint strategy |
| **Iteration Guide** | Do's and don'ts, common failure modes, and rules for modifying the design in later steps |
`DESIGN.md` is also the input format for [Open Design](/guides/open-design) and [Claude Design](/guides/claude-design); both produce a `DESIGN.md` you can drop into a Hyperframes project.
**Gate:** `DESIGN.md` exists with all six sections filled in from real captured data (or chosen deliberately for greenfield projects).
**Gate:** `DESIGN.md` exists with all five sections filled in from real captured data (or chosen deliberately for greenfield projects).
## Step 3: Script
## Step 3: Strategy & Messaging
**Output:** `SCRIPT.md` in the project root
**Output:** Alignment on video type, duration, style, and — critically — the ONE message and narrative arc
`SCRIPT.md` is the narration backbone. Scene durations come from the narration, not from guessing, so write the script before the storyboard and time beats to spoken words.
Before any creative decisions, align with the user on the story this video must tell. Parse the user's prompt first — they probably already gave you the video type and style. Only ask about things they didn't specify. If the prompt is detailed enough, confirm the direction in one message and move to Step 4.
A typical structure: **hook** (one sentence that earns attention), **story** (what the product or topic is), **proof** (numbers, components, customers), **CTA** (one clear action). Reference real features, real stats, and real components from `capture/extracted/visible-text.txt`. Don't invent claims the source doesn't support.
The questions to resolve: what type of video (social ad, product demo, brand reel, etc.), what style and energy, what's the ONE thing this video must communicate, what narrative arc serves that message, and whether narration is wanted.
For videos without narration (brand reels, music-driven teasers), `SCRIPT.md` becomes a per-beat copy plan instead: the on-screen text and headlines, with timing notes.
**Gate:** Video type, duration, format, and the message and narrative arc are locked. Without those, Step 4 can't write a concept-first storyboard.
**Gate:** `SCRIPT.md` exists in the project root.
## Step 4: Storyboard + Script
## Step 4: Storyboard
**Outputs:** `STORYBOARD.md` + `SCRIPT.md` in the project root
**Output:** `STORYBOARD.md` in the project root
Write the storyboard concept-first: message → narrative arc → beats that serve the arc → techniques per beat → brand accents pass at the end. Then write the narration script to match. The storyboard and script are written together — the storyboard drives the script, not the other way around.
`STORYBOARD.md` tells the engineer (human or agent) exactly what to build for each beat: mood, camera, animations, transitions, assets, depth layers, sound effects. It's where the creative choices get pinned down.
@@ -121,9 +120,9 @@ Each beat in `STORYBOARD.md` typically covers:
| Transitions | How this beat enters from the previous one and exits to the next |
| SFX | Short, specific sound effects (e.g. _"woosh on logo entry, soft tick on counter"_) |
The storyboard typically opens with a global-direction block: format, voiceover direction, style basis, and guardrails that apply to every beat.
The storyboard typically opens with a global-direction block: format, voiceover direction, style basis, and guardrails that apply to every beat. `SCRIPT.md` contains the narration backbone: **hook** (one sentence that earns attention), **story** (what the product or topic is), **proof** (numbers, components, customers), **CTA** (one clear action). For videos without narration, `SCRIPT.md` becomes a per-beat copy plan with on-screen text and timing notes.
**Gate:** `STORYBOARD.md` exists with beat-by-beat direction and an asset audit that names every file used.
**Gate:** `STORYBOARD.md` + `SCRIPT.md` exist with beat-by-beat direction, an asset audit that names every file used, and user approval of the plan.
## Step 5: VO and timing
+11 -8
View File
@@ -23,8 +23,8 @@ The installer shows a picker. Select the **core skills** below — every project
| `/hyperframes-core` | Composition contract — HTML structure, `data-*` attributes, clips, tracks |
| `/hyperframes-animation`| All animation — motion rules, scene blueprints, transitions, and the runtime adapters (GSAP, Lottie, Three.js, Anime.js, CSS, WAAPI, TypeGPU) |
| `/hyperframes-creative` | Creative direction — design spec, palettes, typography, narration, beats |
| `/hyperframes-cli` | Dev-loop CLI — `init`, `lint`, `inspect`, `preview`, `render`, `doctor` |
| `/hyperframes-media` | Asset preprocessing — `tts`, `transcribe`, `remove-background` |
| `/hyperframes-cli` | Dev-loop CLI — `init`, `lint`, `validate`, `inspect`, `preview`, `render`, `doctor` |
| `/hyperframes-media` | Audio + media — TTS voiceover, BGM, SFX, transcription, background removal, caption authoring |
| `/hyperframes-registry` | Block and component installation via `hyperframes add` |
| `/general-video` | The general authoring workflow — fallback for any video that doesn't match a specific workflow below |
@@ -39,6 +39,8 @@ The installer shows a picker. Select the **core skills** below — every project
| `/embedded-captions` | An existing talking-head video → the same footage with captions / subtitles |
| `/talking-head-recut` | An existing talking-head video → footage packaged with designed graphic cards |
| `/motion-graphics` | A short, unnarrated, design-led motion graphic (logo sting, kinetic type, stat / chart) |
| `/music-to-video` | A music track (audio file or video) → a beat-synced video (lyric, slideshow, or kinetic promo) |
| `/slideshow` | A presentation / pitch deck / interactive deck — discrete slides, fragment reveals, branching |
| `/remotion-to-hyperframes` | Port an existing Remotion (React) composition to HyperFrames HTML |
<Tip>
@@ -119,7 +121,7 @@ Describe how motion should *feel* and the agent picks the matching GSAP ease:
| Say this | Agent uses | Feels like |
| ----------- | ---------------- | ------------------------------ |
| smooth | `power2.out` | Natural deceleration |
| smooth | `sine` / `power1`| Natural deceleration |
| snappy | `power4.out` | Quick and decisive |
| bouncy | `back.out` | Overshoots then settles |
| springy | `elastic.out` | Oscillates into place |
@@ -182,7 +184,7 @@ Map audio frequency bands to visual properties. The agent uses these defaults:
| Bass | `scale` | Pulse on the beat |
| Treble | `glow` | Shimmer intensity |
| Amplitude | `opacity` | Breathing |
| Mids | `shape` | Morphing |
| Mids | `borderRadius` | Shape morphing |
```
"Make the text pulse with the beat"
@@ -203,8 +205,8 @@ Hand-drawn emphasis effects for text:
| `highlight` | Marker sweep | Key phrases |
| `circle` | Hand-drawn ellipse | Single words |
| `burst` | Radiating lines | Hype moments |
| `scribble` | Chaotic scratch | Crossing out |
| `sketchout` | Rectangle outline | Callouts |
| `scribble` | Chaotic scratch | Rough emphasis|
| `sketchout` | Cross-hatch lines | Crossing out |
```
"Add a marker highlight sweep on 'revolutionary'"
@@ -214,9 +216,9 @@ Hand-drawn emphasis effects for text:
### Text-to-speech voices
TTS runs locally via Kokoro (no API key needed). Describe the content and the agent picks a voice, or request one directly:
HyperFrames supports three TTS providers: **HeyGen** (Starfish voices, requires sign-in via `npx hyperframes auth`), **ElevenLabs** (requires API key), and **Kokoro** (free, runs locally, no API key needed). The agent asks which provider to use — or picks automatically in autonomous mode. Describe the content and the agent picks a voice, or request one directly:
| Content type | Recommended voices |
| Content type | Kokoro voices |
| ------------- | -------------------------- |
| Product demo | `af_heart`, `af_nova` |
| Tutorial | `am_adam`, `bf_emma` |
@@ -226,6 +228,7 @@ TTS runs locally via Kokoro (no API key needed). Describe the content and the ag
"Generate narration for this script"
"Create voiceover with a professional female voice"
"Add TTS with British male voice at 1.1x speed"
"Use HeyGen TTS for this narration"
```
### Rendering quality
+7 -7
View File
@@ -117,13 +117,13 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4, MOV, WebM
|------|--------|---------|-------------|
| `--output` | path | `renders/<name>.mp4` | Output file path |
| `--format` | mp4, mov, webm, gif, png-sequence | mp4 | Output format (see [Transparent Video](#transparent-video) below) |
| `--fps` | 24, 30, 60 | 30 | Frames per second |
| `--fps` | 1-240 or rational (e.g. `30000/1001`) | 30 | Frames per second |
| `--gif-loop` | 0-65535 | 0 | GIF loop count. `0` loops forever |
| `--quality` | draft, standard, high | standard | Encoding quality preset |
| `--crf` | 051 | — | Override CRF (lower = higher quality). Cannot combine with `--video-bitrate` |
| `--video-bitrate` | e.g. `10M`, `5000k` | — | Target bitrate encoding. Cannot combine with `--crf` |
| `--video-frame-format` | auto, jpg, png | auto | Source video frame extraction format. Use `png` for UI recordings, screen captures, and color-sensitive source videos |
| `--workers` | 1-8 or `auto` | auto | Parallel render workers (see [Workers](#workers) below) |
| `--workers` | 1-24 or `auto` | auto | Parallel render workers (see [Workers](#workers) below) |
| `--max-concurrent-renders` | 1-10 | 2 | Max simultaneous renders via the producer server (see [Concurrent Renders](#concurrent-renders) below) |
| `--batch` | path | — | JSON array of variable rows (or `{ "rows": [...] }`), rendering one output per row |
| `--batch-concurrency` | integer | 1 | Maximum batch rows to render at once |
@@ -197,16 +197,16 @@ Each render worker launches a **separate Chrome browser process** to capture fra
### Default behavior
By default, Hyperframes uses **half of your CPU cores, capped at 4**:
By default, Hyperframes uses **CPU cores minus 2** (reserving headroom for FFmpeg encoding and your other applications):
| Machine | CPU cores | Default workers |
|---------|-----------|----------------|
| MacBook Air (M1) | 8 | 4 |
| MacBook Pro (M3) | 12 | 4 (capped) |
| MacBook Air (M1) | 8 | 6 |
| MacBook Pro (M3) | 12 | 10 |
| 4-core laptop | 4 | 2 |
| 2-core VM | 2 | 1 |
This is intentionally conservative. Each worker spawns its own Chrome process, so the per-worker overhead is significant. Fewer workers avoids resource contention with FFmpeg encoding and your other applications.
Each worker spawns its own Chrome process (~256 MB RAM), so the per-worker overhead is significant. The maximum is 24 workers (hard ceiling).
### Choosing a worker count
@@ -218,7 +218,7 @@ npx hyperframes render --workers 1 --output output.mp4
npx hyperframes render --workers auto --output output.mp4
# Maximum parallelism (use with caution on laptops)
npx hyperframes render --workers 8 --output output.mp4
npx hyperframes render --workers 24 --output output.mp4
```
<Tip>
+2 -2
View File
@@ -21,7 +21,7 @@ The skills split into three groups:
Opens a picker so you can choose which skills to add. Works with [Claude Code](https://claude.ai/claude-code), [Cursor](https://cursor.sh), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Codex CLI](https://github.com/openai/codex), [GitHub Copilot CLI](/guides/copilot-cli), and [Google Antigravity](/guides/antigravity).
</Step>
<Step title="Or install all 20 at once (skip the picker)">
<Step title="Or install all 21 at once (skip the picker)">
```bash
npx skills add heygen-com/hyperframes --all
```
@@ -82,7 +82,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
| `/hyperframes-creative` | Non-animation creative direction — `frame.md` / `design.md`, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns. |
| `/hyperframes-media` | Audio + media — TTS voiceover, background music, sound effects, Whisper transcription, background removal, caption authoring (one shared audio engine). |
| `/media-use` | Resolve any media need (BGM, SFX, image, icon) into a frozen local file + ledger record. One verb (`resolve`) over the HeyGen catalog with manifest tracking. |
| `/hyperframes-cli` | CLI dev loop — `init`, `lint`, `validate`, `inspect`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress`). |
| `/hyperframes-cli` | CLI dev loop — `init`, `lint`, `validate`, `inspect`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress / destroy / policies`). |
| `/hyperframes-registry` | Install and wire registry blocks and components into compositions via `hyperframes add`. Authoring a new block or component to contribute upstream. |
| `/figma` | Import Figma assets, tokens, components, and storyboard sections → animatics (REST/CLI) plus Motion animations and shaders (MCP) into a composition. |
+1 -1
View File
@@ -13,7 +13,7 @@ If your issue is about a specific coding mistake (animations not working, video
```html index.html
<div id="root" data-composition-id="my-video"
data-start="0" data-width="1920" data-height="1080">
data-width="1920" data-height="1080">
<!-- elements here -->
</div>
```
+9 -10
View File
@@ -29,7 +29,7 @@ Give your AI agent a URL and a creative direction. It captures the site, extract
Create a 25-second product launch video from https://example.com. Bold, cinematic, dark theme energy.
```
The agent loads the skill when they see a URL and a video request, and runs the full pipeline — capture, design, script, storyboard, voiceover, build, validate.
The agent loads the skill when they see a URL and a video request, and runs the full pipeline — capture, design, strategy & messaging, storyboard + script, voiceover, build, validate.
<Note>
Agents also trigger this skill automatically when they see a URL and a video request.
@@ -65,12 +65,12 @@ The skill follows the [Hyperframes pipeline](/guides/pipeline): seven steps, eac
| Step | Output | What happens |
|------|--------|-------------|
| **Capture** | `capture/` | Extract screenshots, design tokens, fonts, assets, animations |
| **Design** | `DESIGN.md` | Brand reference — colors, typography, do's and don'ts |
| **Script** | `SCRIPT.md` | Narration text with hook, story, proof, CTA |
| **Storyboard** | `STORYBOARD.md` | Per-beat creative direction — mood, assets, animations, transitions |
| **Design** | `DESIGN.md` | Brand reference — colors, typography, component stylings, spacing, iteration guide |
| **Strategy & Messaging** | — | Align on video type, style, the ONE message, and narrative arc |
| **Storyboard + Script** | `STORYBOARD.md` + `SCRIPT.md` | Concept-first storyboard and narration script, written together |
| **VO + Timing** | `narration.wav` + `transcript.json` | TTS audio with word-level timestamps |
| **Build** | `compositions/*.html` | Animated HTML compositions, one per beat |
| **Validate** | Snapshot PNGs | Visual verification before delivery |
| **Validate** | Snapshot PNGs + lint/validate pass | Visual verification and runtime checks before delivery |
See [the pipeline guide](/guides/pipeline) for a detailed walkthrough of each step, the contents of every generated file, and how to iterate without re-running the whole pipeline. The structure is useful for any Hyperframes project, not just website captures.
@@ -81,11 +81,10 @@ The prompt determines the format. Include a duration and creative direction:
| Type | Duration | Example |
|------|----------|---------|
| Social ad | 1015s | _"15-second Instagram reel. Energetic, fast cuts."_ |
| Product launch | 2030s | _"25-second product launch. Apple keynote energy."_ |
| Product tour | 3060s | _"45-second tour showing the top 3 features."_ |
| Brand reel | 1530s | _"20-second brand video. Celebrate the design."_ |
| Feature announcement | 1525s | _"Feature announcement highlighting the new AI agents."_ |
| Teaser | 815s | _"10-second teaser. Super minimal. Just the hook."_ |
| Product demo | 3060s | _"45-second demo showing the top 3 features."_ |
| Feature announcement | 1530s | _"Feature announcement highlighting the new AI agents."_ |
| Brand reel | 2045s | _"30-second brand video. Celebrate the design."_ |
| Launch teaser | 1020s | _"12-second teaser. Super minimal. Just the hook."_ |
<Tip>
Creative direction matters more than format. _"Playful, hand-crafted feel"_ or _"dark, developer-focused, show code"_ shapes the storyboard and drives every visual decision the agent makes.
+5 -3
View File
@@ -667,8 +667,10 @@ Word-level transcripts (whisper output) are grouped into readable caption cues o
| Flag | Values | Default | Description |
|------|--------|---------|-------------|
| `--output` | path | `renders/<name>.mp4` | Output file path |
| `--format` | mp4, webm, mov, png-sequence | mp4 | Output format (WebM/MOV render with transparency; png-sequence writes a directory of RGBA PNGs) |
| `--fps` | 24, 30, 60 | 30 | Frames per second |
| `--composition, -c` | path | `index.html` | Render a specific composition file instead of `index.html` |
| `--format` | mp4, webm, mov, gif, png-sequence | mp4 | Output format (WebM/MOV render with transparency; gif for inline embeds; png-sequence writes a directory of RGBA PNGs) |
| `--fps` | 1-240 or rational (e.g. `30000/1001`) | 30 | Frames per second |
| `--gif-loop` | 0-65535 | 0 | GIF loop count (`0` = loop forever). Only applies with `--format gif` |
| `--quality` | draft, standard, high | standard | Encoding quality preset (drives CRF/bitrate) |
| `--crf` | 0-51 | — | Override encoder CRF (lower = higher quality). Mutually exclusive with `--video-bitrate` |
| `--video-bitrate` | e.g. `10M`, `5000k` | — | Target video bitrate. Mutually exclusive with `--crf` |
@@ -676,7 +678,7 @@ Word-level transcripts (whisper output) are grouped into readable caption cues o
| `--resolution` | landscape, portrait, landscape-4k, portrait-4k, square, square-4k (aliases: `1080p`, `4k`, `uhd`, `1080p-square`, `square-1080p`, `4k-square`) | — | Output resolution preset. Supersamples a smaller composition via Chrome `deviceScaleFactor` so the screenshot lands at the requested dimensions. Aspect ratio must match the composition; the scale must be an integer multiple. Not supported with `--hdr`. See [4K Rendering](/guides/4k-rendering) |
| `--hdr` | — | off | Force HDR output even if no HDR sources are detected. MP4 only. See [HDR Rendering](/guides/hdr) |
| `--sdr` | — | off | Force SDR output even if HDR sources are detected |
| `--workers` | 1-8 | 4 | Parallel render workers |
| `--workers` | 1-24 or `auto` | auto | Parallel render workers (auto = CPU cores minus 2) |
| `--low-memory-mode` / `--no-low-memory-mode` | — | auto (≤ 8 GB RAM) | Force the low-memory safe render profile on or off. Safe mode pins to 1 worker, uses screenshot capture, and skips auto-worker calibration so the pipeline doesn't launch multiple concurrent Chrome instances on constrained machines. Auto-detection reads **host** RAM (`os.totalmem()`), not cgroup/container limits — containerised or serverless callers (incl. `--docker`) should set `PRODUCER_LOW_MEMORY_MODE` explicitly. Env fallback `PRODUCER_LOW_MEMORY_MODE`. |
| `--gpu` | — | off | GPU encoding (NVENC, VideoToolbox, AMF, VAAPI, QSV) |
| `--browser-gpu` / `--no-browser-gpu` | — | on locally, off in Docker | Use or opt out of host GPU acceleration for local Chrome/WebGL capture |
+6 -13
View File
@@ -62,11 +62,6 @@ import {
isTextElement,
isMediaElement,
isCompositionElement,
isStringVariable,
isNumberVariable,
isColorVariable,
isBooleanVariable,
isEnumVariable,
} from '@hyperframes/core';
// Constants
@@ -183,18 +178,16 @@ const result = validateCompositionHtml(html);
```typescript
import {
parseGsapScript,
serializeGsapAnimations,
updateAnimationInScript,
addAnimationToScript,
removeAnimationFromScript,
getAnimationsForElement,
getAnimationsForElementId,
validateCompositionGsap,
keyframesToGsapAnimations,
gsapAnimationsToKeyframes,
SUPPORTED_PROPS, // animatable properties
SUPPORTED_EASES, // available easing functions
} from '@hyperframes/core';
// GSAP parsing, mutation, and constants live in @hyperframes/parsers:
import { parseGsapScript, SUPPORTED_PROPS, SUPPORTED_EASES } from '@hyperframes/parsers/gsap-parser';
import { updateAnimationInScript, addAnimationToScript, removeAnimationFromScript } from '@hyperframes/parsers/gsap-writer-acorn';
import type { GsapAnimation, GsapMethod, ParsedGsap } from '@hyperframes/core';
// Parse GSAP script into structured animations
@@ -258,7 +251,7 @@ import { lintHyperframeHtml, lintMediaUrls } from '@hyperframes/core/lint';
import type {
HyperframeLintResult,
HyperframeLintFinding,
HyperframeLintSeverity, // "error" | "warning"
HyperframeLintSeverity, // "error" | "warning" | "info"
HyperframeLinterOptions,
} from '@hyperframes/core/lint';
+11 -9
View File
@@ -38,7 +38,7 @@ The engine implements a **seek-and-capture** loop that is fundamentally differen
Your HTML composition is loaded into a browser page. The Hyperframes runtime is injected to manage timeline seeking.
</Step>
<Step title="Seek to each frame">
For every frame in the video (e.g., 900 frames for a 30-second video at 30fps), the engine calls `renderSeek(time)` to advance the composition to the exact timestamp. No wall clock is involved — each frame is independently positioned.
For every frame in the video (e.g., 900 frames for a 30-second video at 30fps), the engine calls `window.__hf.seek(time)` to advance the composition to the exact timestamp. No wall clock is involved — each frame is independently positioned.
</Step>
<Step title="Capture via BeginFrame">
Chrome's `HeadlessExperimental.beginFrame` API captures the compositor output as a pixel buffer. This produces pixel-perfect frames without any screen recording artifacts.
@@ -95,14 +95,16 @@ import {
closeCaptureSession,
} from '@hyperframes/engine';
// 1. Create a capture session
const session = await createCaptureSession({ fps: { num: 30, den: 1 }, width: 1920, height: 1080 });
// 1. Create a capture session (serverUrl, outputDir, options)
const session = await createCaptureSession(serverUrl, outputDir, {
fps: { num: 30, den: 1 }, width: 1920, height: 1080,
});
// 2. Initialize with a composition
await initializeSession(session, './my-video/index.html');
// 2. Initialize the session
await initializeSession(session);
// 3. Get the total duration
const duration = getCompositionDuration(session);
// 3. Get the total duration (async)
const duration = await getCompositionDuration(session);
// 4. Capture frames
const totalFrames = Math.ceil(duration * 30);
@@ -227,7 +229,7 @@ const frames = await extractAllVideoFrames(videoPath, { fps: 30 });
// Create a lookup table for fast frame access
const lookup = createFrameLookupTable(frames);
const frame = lookup.getFrameAtTime(5.0);
const frame = lookup.getFrame('video-1', 5.0);
```
### Audio Processing
@@ -384,7 +386,7 @@ For more on how this enables deterministic output, see [Deterministic Rendering]
### Seek Contract
The engine relies on the Hyperframes runtime's `renderSeek(time)` function. When called, `renderSeek`:
The engine relies on the Hyperframes runtime's `window.__hf.seek(time)` function. When called, `seek`:
1. Pauses all GSAP timelines
2. Seeks every timeline to the exact timestamp
+2 -2
View File
@@ -39,7 +39,7 @@ import {
import type {
HyperframeLintResult,
HyperframeLintFinding,
HyperframeLintSeverity, // "error" | "warning"
HyperframeLintSeverity, // "error" | "warning" | "info"
HyperframeLinterOptions,
ProjectLintResult,
} from '@hyperframes/lint';
@@ -74,7 +74,7 @@ const result: ProjectLintResult = await lintProject('./my-composition');
// result.totalErrors, result.totalWarnings, result.results[]
// each result entry: { file, result: HyperframeLintResult }
if (shouldBlockRender(result)) {
if (shouldBlockRender(false, false, result.totalErrors, result.totalWarnings)) {
throw new Error(`Lint found ${result.totalErrors} blocking error(s)`);
}
```
+2
View File
@@ -26,6 +26,7 @@ npm install @hyperframes/parsers
| Import | Description |
|--------|-------------|
| `@hyperframes/parsers` | HTML parser, GSAP serialize/validate helpers, hf-ids, shared types |
| `@hyperframes/parsers/gsap-parser` | GSAP parser exports, `parseGsapScript`, `SUPPORTED_PROPS`, `SUPPORTED_EASES` |
| `@hyperframes/parsers/gsap-parser-acorn` | Acorn-based GSAP parser (browser-safe, read path) |
| `@hyperframes/parsers/gsap-writer-acorn` | Acorn-based GSAP writer (mutation helpers) |
| `@hyperframes/parsers/gsap-parser-recast` | Recast-based GSAP parser/writer (legacy implementation) |
@@ -35,6 +36,7 @@ npm install @hyperframes/parsers
| `@hyperframes/parsers/slideshow` | Slideshow manifest parser (`parseSlideshowManifest`, `resolveSlideshow`) |
| `@hyperframes/parsers/composition` | Pure, browser-safe composition primitives (data types, font aliases, URL helper) |
| `@hyperframes/parsers/asset-paths` | Node-only asset-path rewriting helpers (`rewriteAssetPath`, …) |
| `@hyperframes/parsers/sub-composition-validity` | Sub-composition validation utilities |
<Info>
The package ships subpath entries so consumers tree-shake to what they use — importing `@hyperframes/parsers/hf-ids` (a couple KB) does **not** pull in the GSAP AST machinery (recast/babel/acorn).
+1 -1
View File
@@ -63,7 +63,7 @@ import '@hyperframes/player';
| `controls` | boolean | false | Show playback controls overlay |
| `autoplay` | boolean | false | Start playing on load |
| `loop` | boolean | false | Loop playback |
| `muted` | boolean | true | Mute audio (required for autoplay in most browsers) |
| `muted` | boolean | false | Mute audio (set to `true` for autoplay in most browsers) |
| `poster` | string | — | Image URL to show before first play |
| `playback-rate` | number | 1 | Playback speed multiplier |
+5 -5
View File
@@ -75,8 +75,8 @@ import { createRenderJob } from '@hyperframes/producer';
const job = createRenderJob({
fps: 30, // integer, or { num: 30000, den: 1001 } for NTSC
quality: 'standard', // 'draft', 'standard', or 'high'
format: 'mp4', // 'mp4', 'webm', 'mov', or 'png-sequence'
workers: 4, // Parallel render workers (1-8)
format: 'mp4', // 'mp4', 'webm', 'mov', 'gif', or 'png-sequence'
workers: 4, // Parallel render workers (1-24, or omit for auto)
useGpu: false, // GPU-accelerated encoding
debug: false, // Debug logging
});
@@ -104,20 +104,20 @@ When `format: 'webm'`:
#### HDR Output
Set `hdr: true` to enable HDR detection. The producer probes every video and image source for BT.2020 / PQ / HLG color tagging — if any HDR source is found, the output uses H.265 10-bit BT.2020 with HDR10 static metadata. SDR-only compositions are unaffected.
Set `hdrMode` to control HDR behavior. The producer probes every video and image source for BT.2020 / PQ / HLG color tagging — if any HDR source is found and the mode allows it, the output uses H.265 10-bit BT.2020 with HDR10 static metadata. SDR-only compositions are unaffected.
```typescript
const job = createRenderJob({
fps: 30,
quality: 'standard',
format: 'mp4',
hdr: true,
hdrMode: 'auto', // 'auto' | 'force-hdr' | 'force-sdr'
});
await executeRenderJob(job, './my-video', './output.mp4');
```
When `hdr: true`:
When `hdrMode` is `'auto'` or `'force-hdr'`:
- Sources are probed via `ffprobe`; PQ takes precedence over HLG when both are present
- HDR videos and images are extracted as 16-bit linear-light pixels and composited natively
- SDR DOM overlays are converted from sRGB → BT.2020 before being layered on top
+3
View File
@@ -29,6 +29,7 @@ npm install @hyperframes/studio-server
| Import | Description |
|--------|-------------|
| `@hyperframes/studio-server` | `createStudioApi`, helpers, types |
| `@hyperframes/studio-server/source-mutation` | Source mutation utilities |
| `@hyperframes/studio-server/screenshot-clip` | Element screenshot-clip geometry |
| `@hyperframes/studio-server/manual-edits-render-script` | Manual-edits render body script |
| `@hyperframes/studio-server/studio-motion-render-script` | Studio motion render body script |
@@ -49,6 +50,8 @@ const adapter: StudioApiAdapter = {
bundle: async (projectDir) => bundleToSingleHtml(projectDir),
lint: (html, opts) => lintHyperframeHtml(html, opts),
runtimeUrl: '/hyperframe-runtime.js',
rendersDir: (project) => join(project.dir, 'renders'),
startRender: async (opts) => startRenderJob(opts),
};
const api = createStudioApi(adapter); // → Hono app
+8 -24
View File
@@ -54,7 +54,7 @@ The studio has two entry points:
| `@hyperframes/studio` | React components, hooks, and types |
| `@hyperframes/studio/tailwind-preset` | Tailwind CSS preset for studio styling |
Peer dependencies: `react` (18 or 19), `react-dom` (18 or 19), `zustand` (4 or 5).
Peer dependencies: `react` (19), `react-dom` (19), `zustand` (4 or 5).
## Components
@@ -83,10 +83,8 @@ import {
Player,
PlayerControls,
Timeline,
PreviewPanel,
AgentActivityTrack,
} from '@hyperframes/studio';
import type { AgentActivity, TimelineElement, ActiveEdits } from '@hyperframes/studio';
import type { TimelineElement } from '@hyperframes/studio';
// Embed the preview player
<Player />
@@ -96,12 +94,6 @@ import type { AgentActivity, TimelineElement, ActiveEdits } from '@hyperframes/s
// Timeline editor with scrubber
<Timeline />
// Preview display area
<PreviewPanel />
// Activity visualization track (for agent workflows)
<AgentActivityTrack activities={activities} />
```
### Editor Components
@@ -138,7 +130,8 @@ Manages player state and playback control:
import { useTimelinePlayer } from '@hyperframes/studio';
const player = useTimelinePlayer();
// player.play(), player.pause(), player.seek(time), player.stepForward(), player.stepBackward()
// player.play(), player.pause(), player.togglePlay(), player.seek(time)
// player.refreshPlayer(), player.saveSeekPosition(), player.resetPlayer()
```
### `usePlayerStore`
@@ -155,17 +148,6 @@ const store = usePlayerStore();
const display = formatTime(liveTime.current);
```
### `useCodeEditor`
Code editor state and editing functions:
```typescript
import { useCodeEditor } from '@hyperframes/studio';
const editor = useCodeEditor();
// editor.code, editor.setCode(), editor.diff, editor.onChange()
```
### `useElementPicker`
Element selection from the preview:
@@ -173,8 +155,10 @@ Element selection from the preview:
```typescript
import { useElementPicker } from '@hyperframes/studio';
const picker = useElementPicker();
// picker.selectedElement, picker.selectElement(id), picker.clearSelection()
const picker = useElementPicker(iframeRef);
// picker.isPickMode, picker.pickedElement
// picker.enablePick(), picker.disablePick(), picker.clearPick()
// picker.setStyle(prop, value), picker.setDataAttr(name, value), picker.setTextContent(text)
```
## Features