From db892f4e8f7a55f19d11aba3082800dfd47b437a Mon Sep 17 00:00:00 2001 From: James Date: Thu, 26 Mar 2026 18:23:32 +0000 Subject: [PATCH] docs: audit and fix all documentation against actual codebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive audit of every documentation page against the actual source code, fixing incorrect APIs, wrong CLI flags, nonexistent templates, and missing public exports. Also documents the new agent-friendly CLI design. Key fixes: - Quickstart: `npx create-hyperframe` → `npx hyperframes init`, Node 20→22 - Templates: replaced nonexistent blank/title-card/video-edit with actual templates (blank, warm-grain, play-mode, swiss-grid, vignelli) - CLI: removed nonexistent short flags (-o/-f/-q/-w), added missing commands (browser, docs, telemetry, skills), documented agent-friendly non-interactive default and --human-friendly flag - Producer: replaced nonexistent `render()` API with actual `createRenderJob()`/`executeRenderJob()`, added server API docs - Engine: replaced nonexistent `createEngine()` with actual session-based API, added HfProtocol, encoding, streaming, parallel rendering docs - Core: fixed wrong type names (Composition/Clip→TimelineElement), wrong function names (parseHyperframeHtml→parseHtml), documented all 4 entry points (main, /lint, /compiler, /runtime) - Studio: added all missing exports (NLELayout, SourceEditor, PropertyPanel, FileTree, StudioApp, hooks, Tailwind preset) - All pages: --output not -o, Node 22+ not 20+ Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/concepts/determinism.mdx | 2 +- docs/guides/rendering.mdx | 24 +- docs/guides/templates.mdx | 133 ++++++++--- docs/guides/troubleshooting.mdx | 4 +- docs/introduction.mdx | 10 +- docs/packages/cli.mdx | 254 ++++++++++++++------ docs/packages/core.mdx | 409 ++++++++++++++++++++++++++------ docs/packages/engine.mdx | 215 +++++++++++++++-- docs/packages/producer.mdx | 116 +++++++-- docs/packages/studio.mdx | 157 ++++++++++-- docs/quickstart.mdx | 49 ++-- 11 files changed, 1098 insertions(+), 275 deletions(-) diff --git a/docs/concepts/determinism.mdx b/docs/concepts/determinism.mdx index 11788c6a2..8e7275d38 100644 --- a/docs/concepts/determinism.mdx +++ b/docs/concepts/determinism.mdx @@ -52,7 +52,7 @@ These same rules apply to every [frame adapter](/concepts/frame-adapters). If yo For maximum reproducibility, render in Docker: ```bash -npx hyperframes render --docker -o output.mp4 +npx hyperframes render --docker --output output.mp4 ``` Docker mode uses an exact Chrome version and font set, ensuring: diff --git a/docs/guides/rendering.mdx b/docs/guides/rendering.mdx index 18a3ce22c..388407e09 100644 --- a/docs/guides/rendering.mdx +++ b/docs/guides/rendering.mdx @@ -18,10 +18,11 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4 with the [ Expected output: ``` - ✓ Node.js 20.x - ✓ FFmpeg found (7.x) - ✓ Docker available - ✓ Disk space OK + ✓ Node.js v22.x + ✓ FFmpeg 7.x + ✓ FFprobe 7.x + ✓ Chrome (bundled) + ✓ Docker available ``` @@ -35,7 +36,7 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4 with the [ Run the render command from your project directory: ```bash Terminal - npx hyperframes render -o output.mp4 + npx hyperframes render --output output.mp4 ``` Expected output: @@ -59,7 +60,7 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4 with the [ **Requires:** FFmpeg installed on your system. See [Troubleshooting](/guides/troubleshooting) if FFmpeg is not found. ```bash Terminal - npx hyperframes render -o output.mp4 + npx hyperframes render --output output.mp4 ``` **Pros:** @@ -79,7 +80,7 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4 with the [ **Requires:** Docker installed and running. ```bash Terminal - npx hyperframes render --docker -o output.mp4 + npx hyperframes render --docker --output output.mp4 ``` **Pros:** @@ -112,12 +113,13 @@ Render your Hyperframes [compositions](/concepts/compositions) to MP4 with the [ | Flag | Values | Default | Description | |------|--------|---------|-------------| -| `-f, --fps` | 24, 30, 60 | 30 | Frames per second | -| `-q, --quality` | draft, standard, high | standard | Encoding quality preset | -| `-w, --workers` | 1-8 | auto | Parallel render workers | +| `--output` | path | `renders/.mp4` | Output file path | +| `--fps` | 24, 30, 60 | 30 | Frames per second | +| `--quality` | draft, standard, high | standard | Encoding quality preset | +| `--workers` | 1-8 | 4 | Parallel render workers | | `--gpu` | — | off | GPU encoding (NVENC, VideoToolbox, VAAPI) | -| `-o, --output` | path | — | Output file path | | `--docker` | — | off | Use Docker for [deterministic rendering](/concepts/determinism) | +| `--quiet` | — | off | Suppress verbose output | ## Tips diff --git a/docs/guides/templates.mdx b/docs/guides/templates.mdx index 7f24e5a38..4bd8bf1c3 100644 --- a/docs/guides/templates.mdx +++ b/docs/guides/templates.mdx @@ -11,7 +11,9 @@ Hyperframes includes starter templates to help you scaffold compositions quickly npx hyperframes init --template ``` -This creates a new project directory with an `index.html` composition and any required assets. +This creates a new project directory with an `index.html` composition, sub-compositions, and any required assets. + +You can also run `npx hyperframes init` without `--template` to choose interactively. ## Available Templates @@ -19,77 +21,150 @@ This creates a new project directory with an `index.html` composition and any re ### blank - An empty 1920x1080 composition with a GSAP timeline wired up and nothing else. Start from scratch. + An empty composition with just the scaffolding — a video element, audio track, captions sub-composition, and an empty GSAP timeline. Start from scratch. - **What it produces:** A black (empty) canvas at 1920x1080 resolution. No visible elements, no animations. The timeline is registered and ready for you to add tweens. + **What it produces:** A minimal project with a single video clip and audio, ready for you to customize. The timeline is registered and ready for you to add tweens. - **When to use it:** You have a specific design in mind and want full control. Good for AI agent workflows that will generate the entire composition programmatically. + **When to use it:** You have a specific design in mind and want full control. Good for AI agent workflows that will generate the composition programmatically, or when starting from a source video. ```bash Terminal - npx hyperframes init --template blank + npx hyperframes init my-video --template blank ``` **What you get:** ``` my-video/ - ├── index.html # Empty root composition with GSAP setup - └── assets/ # Empty directory for your media files + ├── meta.json + ├── index.html + └── compositions/ + └── captions.html ``` - - ### title-card + + ### warm-grain - Animated title and subtitle with GSAP fade-in/out transitions. + A cream-toned aesthetic with grain texture overlay. Warm, organic feel suited for lifestyle and branding videos. - **What it produces:** A centered title and subtitle that fade in from the top, hold for a few seconds, then fade out. Clean, minimal typography on a solid background. Good for intro cards, chapter markers, or end screens. + **What it produces:** A composition with warm color grading, textured grain, and smooth transitions. Includes an intro sub-composition and captions support. - **When to use it:** You need a simple text-based segment — an intro, outro, or interstitial card between video clips. + **When to use it:** You want an organic, stylized look for branding, lifestyle, or editorial content. ```bash Terminal - npx hyperframes init --template title-card + npx hyperframes init my-video --template warm-grain ``` **What you get:** ``` my-video/ - ├── index.html # Title + subtitle with fade animations - └── assets/ # Empty directory for your media files + ├── meta.json + ├── index.html + ├── compositions/ + │ ├── intro.html + │ ├── graphics.html + │ └── captions.html + └── assets/ ``` - - ### video-edit + + ### play-mode - A video element with trimming, audio, and track controls. + Playful elastic animations with bold, energetic motion. - **What it produces:** A full-screen video clip with [`data-media-start`](/concepts/data-attributes#media-attributes) for trimming, a background audio track on a separate [timeline track](/concepts/data-attributes#timing-attributes), and a lower-third text overlay animated with GSAP. Demonstrates how multiple clip types work together. + **What it produces:** A composition with bouncy, elastic animation curves and dynamic layout transitions. Includes intro, stats, and captions sub-compositions. - **When to use it:** You are building a video editing workflow — cutting clips, adding overlays, mixing audio. This template shows the patterns for media-heavy compositions. + **When to use it:** You want a fun, high-energy feel — great for social media, product launches, or explainer videos. ```bash Terminal - npx hyperframes init --template video-edit + npx hyperframes init my-video --template play-mode ``` **What you get:** ``` my-video/ - ├── index.html # Video + audio + overlay composition - └── assets/ # Place your video and audio files here + ├── meta.json + ├── index.html + ├── compositions/ + │ ├── intro.html + │ ├── stats.html + │ └── captions.html + └── assets/ + ``` + + + ### swiss-grid + + Structured grid layout inspired by Swiss/International Typographic Style. + + **What it produces:** A clean, grid-based composition with precise typography and structured layouts. Includes intro, graphics, and captions sub-compositions. + + **When to use it:** You want a clean, professional, information-dense layout — ideal for corporate videos, data presentations, or technical content. + + ```bash Terminal + npx hyperframes init my-video --template swiss-grid + ``` + + **What you get:** + ``` + my-video/ + ├── meta.json + ├── index.html + ├── compositions/ + │ ├── intro.html + │ ├── graphics.html + │ └── captions.html + └── assets/ + ``` + + + ### vignelli + + Bold typography with red accents, inspired by Massimo Vignelli's design philosophy. + + **What it produces:** A striking composition with strong typographic hierarchy, red accent colors, and confident transitions. Includes overlays and captions sub-compositions. + + **When to use it:** You want a bold, authoritative visual style — great for headlines, announcements, or editorial content. + + ```bash Terminal + npx hyperframes init my-video --template vignelli + ``` + + **What you get:** + ``` + my-video/ + ├── meta.json + ├── index.html + ├── compositions/ + │ ├── overlays.html + │ └── captions.html + └── assets/ ``` ## Choosing a Template -| Template | Best for | Complexity | -|----------|----------|------------| -| `blank` | Full control, agent-generated compositions | Minimal | -| `title-card` | Text intros, outros, chapter markers | Simple | -| `video-edit` | Video cutting, overlays, multi-track editing | Moderate | +| Template | Style | Best for | +|----------|-------|----------| +| `blank` | Minimal scaffolding | Full control, agent-generated, starting from video | +| `warm-grain` | Organic, textured | Lifestyle, branding, editorial | +| `play-mode` | Energetic, elastic | Social media, product launches | +| `swiss-grid` | Clean, structured | Corporate, data, technical | +| `vignelli` | Bold, typographic | Headlines, announcements | - If you are new to Hyperframes, start with `title-card` to see a working animation, then move to `blank` when you are comfortable with the [composition model](/concepts/compositions) and [GSAP animation](/guides/gsap-animation). + If you are new to Hyperframes, start with `warm-grain` or `play-mode` to see working animations and sub-compositions in action. Use `blank` when you want minimal scaffolding and full control. Run `npx hyperframes init` without `--template` to preview all options interactively. +## Passing a Source Video + +You can initialize a project with your own video file using the `--video` flag: + +```bash Terminal +npx hyperframes init my-video --template warm-grain --video ./my-clip.mp4 +``` + +The CLI will probe the video for duration, resolution, and codec. If the video uses an incompatible codec (not H.264, VP8/9, AV1, or Theora), it will be automatically transcoded to H.264 MP4 if FFmpeg is available. + ## Custom Templates Any directory with an `index.html` can serve as a template. You can copy a directory manually or build your own init workflow. diff --git a/docs/guides/troubleshooting.mdx b/docs/guides/troubleshooting.mdx index 5458cef33..1ab0ad6d6 100644 --- a/docs/guides/troubleshooting.mdx +++ b/docs/guides/troubleshooting.mdx @@ -44,7 +44,7 @@ If your issue is about a specific coding mistake (animations not working, video After installing, run `npx hyperframes doctor` to verify the CLI can find it. - If you cannot install FFmpeg, use [Docker mode](/guides/rendering) instead — it bundles FFmpeg inside the container: `npx hyperframes render --docker -o output.mp4` + If you cannot install FFmpeg, use [Docker mode](/guides/rendering) instead — it bundles FFmpeg inside the container: `npx hyperframes render --docker --output output.mp4` @@ -79,7 +79,7 @@ If your issue is about a specific coding mistake (animations not working, video - **System-specific rendering** — GPU compositing, subpixel antialiasing, etc. ```bash Terminal - npx hyperframes render --docker -o output.mp4 + npx hyperframes render --docker --output output.mp4 ``` See [Rendering: When to Use Each Mode](/guides/rendering#when-to-use-each-mode) for guidance on choosing between local and Docker rendering. diff --git a/docs/introduction.mdx b/docs/introduction.mdx index aac295f03..c72ec1c3a 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -27,7 +27,7 @@ Here is a video defined entirely as HTML: ``` -Run `npx hyperframes render -o demo.mp4` and this produces an MP4 with deterministic, frame-by-frame capture. Same input, identical output, every time. No timeline editor. No proprietary format. Just HTML. +Run `npx hyperframes render --output demo.mp4` and this produces an MP4 with deterministic, frame-by-frame capture. Same input, identical output, every time. No timeline editor. No proprietary format. Just HTML. ## Why Hyperframes? @@ -36,7 +36,7 @@ Run `npx hyperframes render -o demo.mp4` and this produces an MP4 with determini **You already know the stack.** Compositions are HTML files with data attributes. Animations use GSAP, Lottie, CSS, or any runtime that can seek to a given frame. There is no custom DSL, no proprietary component system, and no React requirement. If you can build a web page, you can build a video. - **Agents already speak HTML.** Most video tools require complex APIs or drag-and-drop interfaces that agents cannot operate. Hyperframes compositions are plain HTML documents — the format LLMs are best at generating. An agent can compose, modify, and render videos using tools it already understands. + **Agents already speak HTML.** Most video tools require complex APIs or drag-and-drop interfaces that agents cannot operate. Hyperframes compositions are plain HTML documents — the format LLMs are best at generating. The CLI is non-interactive by default — all inputs via flags, plain text output, fail-fast on errors — so agents can drive every command without prompts or parsing. **Determinism by design.** The rendering pipeline is seek-driven with no wall-clock dependencies. `frame = floor(time * fps)` — every frame is independently captured via Chrome's `beginFrame` API and encoded with FFmpeg. Same input always produces identical output, making CI testing and batch rendering reliable. @@ -44,7 +44,7 @@ Run `npx hyperframes render -o demo.mp4` and this produces an MP4 with determini - Hyperframes was designed from the ground up for AI agent integration. Because compositions are plain HTML, any LLM can generate, edit, and iterate on video content without specialized tooling. Pair it with function-calling agents to build fully automated video pipelines. + Hyperframes was designed from the ground up for AI agent integration. Compositions are plain HTML that any LLM can generate. The CLI is non-interactive by default — flag-driven with plain text output — so agents can scaffold, render, and lint without interactive prompts. Add `--human-friendly` for the interactive terminal UI. See [CLI](/packages/cli) for details. ## How It Works @@ -54,10 +54,10 @@ Run `npx hyperframes render -o demo.mp4` and this produces an MP4 with determini Define your video as an HTML document. Each element gets data attributes for timing (`data-start`, `data-duration`) and layout (`data-track-index`). Add animations with GSAP, Lottie, CSS transitions, or any seekable runtime via the Frame Adapter pattern. - Run `npx hyperframes dev` to open a live preview at `localhost:3000`. Edit your HTML and see changes instantly — no build step, no compilation. + Run `npx hyperframes dev` to open a live preview in your browser. Edit your HTML and see changes instantly — no build step, no compilation. - Run `npx hyperframes render -o output.mp4` to produce a final video. The engine seeks each frame in headless Chrome, captures it with `beginFrame`, and pipes the result through FFmpeg. Run locally or in Docker for fully reproducible output. + Run `npx hyperframes render --output output.mp4` to produce a final video. The engine seeks each frame in headless Chrome, captures it with `beginFrame`, and pipes the result through FFmpeg. Run locally or in Docker for fully reproducible output. diff --git a/docs/packages/cli.mdx b/docs/packages/cli.mdx index 4a2a9c605..d2e3f7dbd 100644 --- a/docs/packages/cli.mdx +++ b/docs/packages/cli.mdx @@ -30,35 +30,56 @@ npx hyperframes The CLI is the recommended starting point for all Hyperframes users. It wraps the producer, engine, and studio packages so you do not need to install them separately. +## Agent-Friendly by Default + +The CLI is **non-interactive by default** — designed so AI agents (Claude Code, Gemini CLI, Codex, Cursor) can drive every command without prompts or interactive UI. + +- All inputs are passed via flags (e.g., `--template`, `--video`, `--output`) +- Missing required flags fail fast with a clear error and usage example +- Output is plain text suitable for parsing +- No interactive prompts, spinners, or selection menus + +Add `--human-friendly` to any command to enable the interactive terminal UI with prompts, spinners, and selection menus. + + + + ```bash + # Fully non-interactive — all inputs from flags + npx hyperframes init my-video --template blank --video video.mp4 + npx hyperframes render --output output.mp4 --fps 30 --quality standard + npx hyperframes upgrade --check + ``` + + + ```bash + # Interactive prompts, spinners, and selection menus + npx hyperframes init --human-friendly + npx hyperframes upgrade + ``` + + + ## Getting Started Scaffold a new composition from a template: ```bash - npx hyperframes init --template title-card + npx hyperframes init --template warm-grain ``` - ``` - Creating composition in ./title-card... - index.html - assets/ - package.json - Done! Run `cd title-card && npx hyperframes dev` to preview. + You will be prompted for a project name, or pass it as an argument: + ```bash + npx hyperframes init my-video --template warm-grain ``` See [Templates](/guides/templates) for all available templates. Start the development server with live hot reload: ```bash - cd title-card + cd my-video npx hyperframes dev ``` - ``` - Hyperframes Studio v0.1.0 - Local: http://localhost:3000 - Watching for changes... - ``` - Edit `index.html` and the preview updates instantly. + The Hyperframes Studio opens in your browser. Edit `index.html` and the preview updates instantly. Check for structural issues before rendering: @@ -73,16 +94,11 @@ npx hyperframes Produce the final video: ```bash - npx hyperframes render -o output.mp4 - ``` - ``` - Rendering index.html... - [========================================] 100% (900/900 frames) - Output: output.mp4 (30s, 1920x1080, 30fps) + npx hyperframes render --output output.mp4 ``` For deterministic output, add `--docker`: ```bash - npx hyperframes render --docker -o output.mp4 + npx hyperframes render --docker --output output.mp4 ``` @@ -96,17 +112,35 @@ npx hyperframes Create a new composition project from a template: ```bash - npx hyperframes init --template + # Agent mode (default) — --template is required + npx hyperframes init my-video --template blank --video video.mp4 + + # Human mode — interactive prompts + npx hyperframes init --human-friendly ``` + | Flag | Description | + |------|-------------| + | `--template, -t` | Template to use (required in default mode, interactive in `--human-friendly`) | + | `--video, -V` | Path to a video file (MP4, WebM, MOV) | + | `--audio, -a` | Path to an audio file (MP3, WAV, M4A) | + | `--skip-skills` | Skip AI coding skills installation | + | `--skip-transcribe` | Skip automatic whisper transcription | + | `--human-friendly` | Enable interactive terminal UI with prompts | + | Template | Description | |----------|-------------| - | `blank` | Empty 1920x1080 composition with a GSAP timeline wired up | - | `title-card` | Animated title and subtitle with GSAP fade-in/out | - | `slideshow` | Image slideshow with crossfade transitions | - | `lower-third` | Broadcast-style lower-third overlay | + | `blank` | Empty composition — just the scaffolding | + | `warm-grain` | Cream aesthetic with grain texture | + | `play-mode` | Playful elastic animations | + | `swiss-grid` | Structured grid layout | + | `vignelli` | Bold typography with red accents | - See [Templates](/guides/templates) for full details and previews. + In default (agent) mode, `--template` is required — the CLI errors with a usage example if missing. In `--human-friendly` mode, you choose interactively. When `--video` or `--audio` is provided, the CLI automatically transcribes the audio with Whisper and patches captions into the composition (use `--skip-transcribe` to disable). + + After scaffolding, the CLI installs AI coding skills for Claude Code, Gemini CLI, and Codex CLI (use `--skip-skills` to disable). See [`skills`](#skills) command. + + See [Templates](/guides/templates) for full details. ### `compositions` @@ -115,11 +149,12 @@ npx hyperframes ```bash npx hyperframes compositions ``` - ``` - Compositions in ./my-video: - root index.html (30s, 1920x1080) - intro-anim compositions/intro.html (5s, 1920x1080) - ``` + + | Flag | Description | + |------|-------------| + | `--json` | Output as JSON | + + Shows each composition's ID, duration, resolution, and element count. ### `dev` @@ -127,22 +162,17 @@ npx hyperframes Start a live preview server with hot reload: ```bash - npx hyperframes dev - ``` - ``` - Hyperframes Studio v0.1.0 - Local: http://localhost:3000 - Watching for changes... + npx hyperframes dev [dir] ``` - Opens your composition in the browser. Edits to `index.html` and any referenced sub-compositions are reflected instantly. The preview uses the same Hyperframes runtime as production rendering, so what you see is what you get. + Opens your composition in the Hyperframes Studio with live preview. Edits to `index.html` and any referenced sub-compositions are reflected instantly. The preview uses the same Hyperframes runtime as production rendering, so what you see is what you get. ### `lint` Check a composition for common issues: ```bash - npx hyperframes lint + npx hyperframes lint [dir] ``` ``` Linting index.html... @@ -154,6 +184,10 @@ npx hyperframes 1 issue found (0 errors, 1 warning) ``` + | Flag | Description | + |------|-------------| + | `--json` | Output findings as JSON | + The linter detects missing attributes, deprecated names, structural problems, and more. See [Common Mistakes](/guides/common-mistakes) for details on each rule. @@ -163,20 +197,25 @@ npx hyperframes ```bash # Local mode (fast iteration) - npx hyperframes render -o output.mp4 + npx hyperframes render --output output.mp4 # Docker mode (deterministic output) - npx hyperframes render --docker -o output.mp4 + npx hyperframes render --docker --output output.mp4 # With options - npx hyperframes render -o output.mp4 --fps 60 --quality high - ``` - ``` - Rendering index.html... - [========================================] 100% (900/900 frames) - Output: output.mp4 (30s, 1920x1080, 30fps) + npx hyperframes render --output output.mp4 --fps 60 --quality high ``` + | Flag | Values | Default | Description | + |------|--------|---------|-------------| + | `--output` | path | `renders/.mp4` | Output file path | + | `--fps` | 24, 30, 60 | 30 | Frames per second | + | `--quality` | draft, standard, high | standard | Encoding quality preset | + | `--workers` | 1-8 | 4 | Parallel render workers | + | `--gpu` | — | off | GPU encoding (NVENC, VideoToolbox, VAAPI) | + | `--docker` | — | off | Use Docker for [deterministic rendering](/concepts/determinism) | + | `--quiet` | — | off | Suppress verbose output | + See [Rendering](/guides/rendering) for all options and modes. ### `benchmark` @@ -184,18 +223,15 @@ npx hyperframes Find optimal render settings for your system: ```bash - npx hyperframes benchmark + npx hyperframes benchmark [dir] ``` - ``` - Running benchmark suite... - Quality: draft FPS: 30 Time: 4.2s Speed: 7.1x realtime - Quality: standard FPS: 30 Time: 8.7s Speed: 3.4x realtime - Quality: high FPS: 30 Time: 15.1s Speed: 2.0x realtime - Quality: standard FPS: 60 Time: 16.3s Speed: 1.8x realtime + | Flag | Values | Default | Description | + |------|--------|---------|-------------| + | `--runs` | 1-20 | 3 | Number of runs per configuration | + | `--json` | — | off | Output results as JSON | - Recommended: quality=standard fps=30 (best speed/quality balance) - ``` + Runs multiple render configurations (varying fps, quality, and worker count) and compares timing and file size for each. ### `doctor` @@ -207,44 +243,110 @@ npx hyperframes ``` ``` Checking environment... - Node.js v20.11.0 OK - FFmpeg 6.1.1 OK - Docker 24.0.7 OK - Chrome 120.0.6099 OK (bundled) + ✓ Node.js v22.x + ✓ FFmpeg 7.x + ✓ FFprobe 7.x + ✓ Chrome (bundled) + ✓ Docker 24.x + ✓ Docker running All checks passed. ``` - Verifies Node.js version, FFmpeg, Docker, Chrome, and other requirements. + Verifies Node.js version, FFmpeg, FFprobe, Chrome, and Docker availability. ### `info` - Display system and project information: + Display project metadata: ```bash - npx hyperframes info - ``` - ``` - Hyperframes v0.1.0 - Node.js v20.11.0 - Platform linux x64 - FFmpeg 6.1.1 - Project ./my-video (2 compositions) + npx hyperframes info [dir] ``` + | Flag | Description | + |------|-------------| + | `--json` | Output as JSON | + + Shows project name, resolution, duration, element counts by type, track count, and total project size. + ### `upgrade` - Update Hyperframes to the latest version: + Check for updates and show upgrade instructions: ```bash npx hyperframes upgrade + npx hyperframes upgrade --check # check and exit (no prompt) + npx hyperframes upgrade --yes # show upgrade commands without prompting ``` + + | Flag | Description | + |------|-------------| + | `--check` | Check for updates and exit (no prompt, agent-friendly) | + | `--yes, -y` | Show upgrade commands without prompting | + + Compares your installed version against the latest on npm and provides upgrade commands. + + ### `browser` + + Manage the Chrome browser used for rendering: + + ```bash + # Find or download Chrome for rendering + npx hyperframes browser ensure + + # Print the browser executable path (for scripting) + npx hyperframes browser path + + # Remove cached Chrome download + npx hyperframes browser clear ``` - Current: 0.1.0 - Latest: 0.2.0 - Upgrading... - Done! Run `npx hyperframes doctor` to verify. + + The `path` subcommand outputs only the path, useful in scripts: `$(npx hyperframes browser path)`. + + ### `docs` + + View inline documentation in the terminal: + + ```bash + npx hyperframes docs [topic] ``` + + Available topics: `data-attributes`, `templates`, `rendering`, `gsap`, `troubleshooting`, `compositions`. Run without a topic to see the full list. + + ### `telemetry` + + Manage anonymous usage telemetry: + + ```bash + npx hyperframes telemetry enable + npx hyperframes telemetry disable + npx hyperframes telemetry status + ``` + + Telemetry collects command names, render performance, template choices, and system info. It does **not** collect file paths, project names, video content, or personally identifiable information. Disable with `HYPERFRAMES_NO_TELEMETRY=1` or the command above. + + ### `skills` + + Install HyperFrames and GSAP skills for AI coding tools: + + ```bash + # Install to all default targets (Claude Code, Gemini CLI, Codex CLI) + npx hyperframes skills + + # Install to specific tools + npx hyperframes skills --claude + npx hyperframes skills --cursor + npx hyperframes skills --claude --gemini + ``` + + | Flag | Description | + |------|-------------| + | `--claude` | Install to Claude Code (`~/.claude/skills/`) | + | `--gemini` | Install to Gemini CLI (`~/.gemini/skills/`) | + | `--codex` | Install to Codex CLI (`~/.codex/skills/`) | + | `--cursor` | Install to Cursor (`.cursor/skills/` in current project) | + + Skills are fetched from GitHub and include composition authoring, GSAP animation patterns, and other domain-specific knowledge. The `init` command also offers to install skills automatically after scaffolding a project. diff --git a/docs/packages/core.mdx b/docs/packages/core.mdx index 7ec889c54..08b76187e 100644 --- a/docs/packages/core.mdx +++ b/docs/packages/core.mdx @@ -27,35 +27,224 @@ npm install @hyperframes/core - Render compositions to MP4 — use the [CLI](/packages/cli) (`npx hyperframes render`) or [producer](/packages/producer) - Capture frames from a headless browser — use the [engine](/packages/engine) -## What's Inside +## Package Exports -| Module | Description | +The core package has four entry points: + +| Import | Description | |--------|-------------| -| `core.types` | TypeScript types for compositions, clips, timelines, and render config | -| `parsers/` | HTML-to-composition parsing — turns an HTML string into a typed `Composition` object | -| `generators/` | Composition-to-HTML generation — turns a `Composition` object back into HTML | -| `runtime/` | The Hyperframes runtime that manages playback, seeking, and clip lifecycle | -| `lint/` | Composition linter with rules for structural correctness | -| `adapters/` | Frame Adapter types and the built-in GSAP adapter | -| `templates/` | HTML composition templates used by `hyperframes init` | +| `@hyperframes/core` | Types, parsers, generators, templates, adapters, runtime utilities | +| `@hyperframes/core/lint` | Composition linter | +| `@hyperframes/core/compiler` | Timing compiler, HTML compiler, bundler, static guard | +| `@hyperframes/core/runtime` | Pre-built IIFE runtime for browser injection | + +## Types + +The core type system models compositions, timeline elements, and variables: + +```typescript +import type { + TimelineElement, + TimelineMediaElement, + TimelineTextElement, + TimelineCompositionElement, + TimelineElementType, // "video" | "image" | "text" | "audio" | "composition" + CompositionSpec, + CompositionVariable, + CanvasResolution, // "landscape" | "portrait" + Orientation, // "16:9" | "9:16" + FrameAdapter, + FrameAdapterContext, +} from '@hyperframes/core'; + +// Type guards +import { + isTextElement, + isMediaElement, + isCompositionElement, + isStringVariable, + isNumberVariable, + isColorVariable, + isBooleanVariable, + isEnumVariable, +} from '@hyperframes/core'; + +// Constants +import { + CANVAS_DIMENSIONS, // { landscape: { width, height }, portrait: { width, height } } + TIMELINE_COLORS, + DEFAULT_DURATIONS, +} from '@hyperframes/core'; +``` + +### Variable Types + +Compositions can expose typed variables for dynamic content: + +```typescript +import type { + CompositionVariableType, // "string" | "number" | "color" | "boolean" | "enum" + StringVariable, + NumberVariable, + ColorVariable, + BooleanVariable, + EnumVariable, +} from '@hyperframes/core'; +``` + +### Keyframe Types + +```typescript +import type { + Keyframe, + KeyframeProperties, + ElementKeyframes, + StageZoom, + StageZoomKeyframe, +} from '@hyperframes/core'; + +import { getDefaultStageZoom } from '@hyperframes/core'; +``` + +## Parsing and Generating HTML + +Round-trip between HTML and structured data: + +```typescript +import { parseHtml, generateHyperframesHtml } from '@hyperframes/core'; +import type { ParsedHtml, CompositionMetadata } from '@hyperframes/core'; + +// Parse HTML into structured data +const parsed: ParsedHtml = parseHtml(htmlString); +// parsed.elements, parsed.gsapScript, parsed.styles, parsed.resolution, parsed.keyframes + +// Extract composition metadata +import { extractCompositionMetadata } from '@hyperframes/core'; +const meta: CompositionMetadata = extractCompositionMetadata(htmlString); +// meta.id, meta.duration, meta.width, meta.height, meta.variables + +// Generate HTML from structured data +const html = generateHyperframesHtml(elements, { + animations, + styles, + resolution: 'landscape', + compositionId: 'my-video', +}); +``` + +### Modifying HTML + +```typescript +import { + updateElementInHtml, + addElementToHtml, + removeElementFromHtml, + validateCompositionHtml, +} from '@hyperframes/core'; + +// Update an element's properties +const updatedHtml = updateElementInHtml(html, 'el-1', { start: 5 }); + +// Add a new element +const newHtml = addElementToHtml(html, newElement); + +// Remove an element +const cleanHtml = removeElementFromHtml(html, 'el-1'); + +// Validate HTML structure +const result = validateCompositionHtml(html); +// result.valid, result.errors +``` + +### GSAP Script Parsing + +```typescript +import { + parseGsapScript, + serializeGsapAnimations, + updateAnimationInScript, + addAnimationToScript, + removeAnimationFromScript, + getAnimationsForElement, + validateCompositionGsap, + keyframesToGsapAnimations, + gsapAnimationsToKeyframes, + SUPPORTED_PROPS, // animatable properties + SUPPORTED_EASES, // available easing functions +} from '@hyperframes/core'; +import type { GsapAnimation, GsapMethod, ParsedGsap } from '@hyperframes/core'; + +// Parse GSAP script into structured animations +const parsed: ParsedGsap = parseGsapScript(scriptContent); +// parsed.animations, parsed.timelineVar, parsed.preamble, parsed.postamble + +// Serialize back to script +const script = serializeGsapAnimations(parsed.animations); +``` + +### HTML Generation + +```typescript +import { + generateHyperframesHtml, + generateGsapTimelineScript, + generateHyperframesStyles, +} from '@hyperframes/core'; + +// Generate a complete HTML composition +const html = generateHyperframesHtml(elements, options); + +// Generate just the GSAP script +const script = generateGsapTimelineScript(animations, options); + +// Generate CSS styles +const { coreCss, customCss, googleFontsLink } = generateHyperframesStyles( + elements, 'landscape', customStyles +); +``` + +### Template Utilities + +```typescript +import { + generateBaseHtml, + getStageStyles, + GSAP_CDN, + BASE_STYLES, + ELEMENT_BASE_STYLES, + MEDIA_STYLES, + TEXT_STYLES, + ZOOM_CONTAINER_STYLES, +} from '@hyperframes/core'; + +// Generate base HTML structure for a resolution +const baseHtml = generateBaseHtml('landscape'); +const styles = getStageStyles('portrait'); +``` ## Linter The composition linter checks for structural issues that would cause rendering failures or unexpected behavior. You can run it from the CLI with `npx hyperframes lint`, or call it programmatically: ```typescript -import { lintHyperframeHtml } from '@hyperframes/core'; +import { lintHyperframeHtml, lintMediaUrls } from '@hyperframes/core/lint'; +import type { + HyperframeLintResult, + HyperframeLintFinding, + HyperframeLintSeverity, // "error" | "warning" + HyperframeLinterOptions, +} from '@hyperframes/core/lint'; -const html = ` -
- -
-`; +const result: HyperframeLintResult = lintHyperframeHtml(html, { filePath: 'index.html' }); +// result.ok, result.errorCount, result.warningCount, result.findings -const issues = lintHyperframeHtml(html); -// => [{ rule: "unmuted-video", message: "Video element 'clip-1' should have the 'muted' attribute ...", severity: "warning" }] +for (const finding of result.findings) { + console.log(finding.severity, finding.code, finding.message); + // finding.file, finding.selector, finding.elementId, finding.fixHint, finding.snippet +} + +// Additional media URL validation +const mediaFindings = lintMediaUrls(result.findings); ``` Detected issues include: @@ -71,77 +260,153 @@ Detected issues include: For a full list of what the linter catches and how to fix each issue, see [Common Mistakes](/guides/common-mistakes) and [Troubleshooting](/guides/troubleshooting). -## Types +## Compiler -Import the core types for use in your own tooling or integrations: +The compiler sub-package handles timing resolution, HTML compilation, and bundling: ```typescript +// Timing compiler (browser-safe — no Node.js dependencies) +import { + compileTimingAttrs, + injectDurations, + extractResolvedMedia, + clampDurations, +} from '@hyperframes/core/compiler'; import type { - Composition, - Clip, - RenderConfig, - FrameAdapterContext, + UnresolvedElement, + ResolvedDuration, + ResolvedMediaElement, + CompilationResult, +} from '@hyperframes/core/compiler'; + +// Compile timing attributes from HTML +const compiled: CompilationResult = compileTimingAttrs(html); + +// Inject resolved durations back into HTML +const updatedHtml = injectDurations(html, compiled.durations); + +// Extract resolved media elements +const media: ResolvedMediaElement[] = extractResolvedMedia(html); +``` + +```typescript +// HTML compiler (Node.js — requires media probing) +import { compileHtml } from '@hyperframes/core/compiler'; +import type { MediaDurationProber } from '@hyperframes/core/compiler'; + +const prober: MediaDurationProber = async (src) => getDuration(src); +const compiledHtml = await compileHtml(html, prober); +``` + +```typescript +// HTML bundler (Node.js — bundles to single file) +import { bundleToSingleHtml } from '@hyperframes/core/compiler'; +import type { BundleOptions } from '@hyperframes/core/compiler'; + +const bundled = await bundleToSingleHtml({ entryPath: './index.html', inline: true }); +``` + +```typescript +// Static guard — validate HTML contract +import { validateHyperframeHtmlContract } from '@hyperframes/core/compiler'; +import type { + HyperframeStaticGuardResult, + HyperframeStaticFailureReason, +} from '@hyperframes/core/compiler'; + +const guard: HyperframeStaticGuardResult = validateHyperframeHtmlContract(html); +// guard.ok, guard.failures[] +// Failure reasons: "missing_composition_id" | "missing_composition_dimensions" +// | "missing_timeline_registry" | "invalid_script_syntax" +// | "invalid_static_hyperframe_contract" +``` + +## Runtime + +The Hyperframes runtime manages playback, seeking, and clip lifecycle in the browser. The core package provides utilities for building and loading the runtime: + +```typescript +import { + loadHyperframeRuntimeSource, + buildHyperframesRuntimeScript, + HYPERFRAME_RUNTIME_ARTIFACTS, + HYPERFRAME_RUNTIME_CONTRACT, + HYPERFRAME_RUNTIME_GLOBALS, + HYPERFRAME_BRIDGE_SOURCES, + HYPERFRAME_CONTROL_ACTIONS, +} from '@hyperframes/core'; +import type { + HyperframeControlAction, + HyperframesRuntimeBuildOptions, } from '@hyperframes/core'; -// Example: define a render configuration -const config: RenderConfig = { - fps: 30, - width: 1920, - height: 1080, - quality: 'standard', -}; +// Load the pre-built runtime IIFE +const runtimeSource = loadHyperframeRuntimeSource(); -// Example: work with a parsed composition -function getClipCount(composition: Composition): number { - return composition.clips.length; -} +// Build a custom runtime script +const script = buildHyperframesRuntimeScript(options); ``` -## Parsing and Generating HTML - -Round-trip between HTML and structured data: +The pre-built runtime IIFE is available as a direct import: ```typescript -import { parseHyperframeHtml, generateHyperframeHtml } from '@hyperframes/core'; - -// Parse HTML into a Composition object -const composition = parseHyperframeHtml(htmlString); -console.log(composition.id); // "root" -console.log(composition.width); // 1920 -console.log(composition.clips); // [{ id: "clip-1", start: 0, ... }, ...] - -// Generate HTML from a Composition object -const html = generateHyperframeHtml(composition); +import runtime from '@hyperframes/core/runtime'; ``` -This is especially useful for AI agents that generate video programmatically — they can construct a `Composition` object in code and then serialize it to HTML for rendering. - -## Runtime Builds - -The runtime is the JavaScript that runs inside the browser (or headless Chrome) to manage clip lifecycle, media playback, and timeline synchronization. It is built in two formats: - -- **`hyperframe.runtime.iife.js`** — injected into browser iframes for preview playback -- **`hyperframe.runtime.mjs`** — for Node.js tooling and tests - -Build the runtime from source: - -```bash -bun run --filter @hyperframes/core build:hyperframes-runtime -``` - - - You should not need to build the runtime yourself unless you are developing the Hyperframes framework itself. The CLI and producer packages bundle the runtime automatically. - - ## Frame Adapters -The core package defines the [Frame Adapter](/concepts/frame-adapters) interface — the abstraction that lets Hyperframes work with any animation runtime. The built-in GSAP adapter lives here: +The core package defines the [Frame Adapter](/concepts/frame-adapters) interface and provides the built-in GSAP adapter: ```typescript -import type { FrameAdapterContext } from '@hyperframes/core'; +import { createGSAPFrameAdapter } from '@hyperframes/core'; +import type { + FrameAdapter, + FrameAdapterContext, + GSAPTimelineLike, + CreateGSAPFrameAdapterOptions, +} from '@hyperframes/core'; -// Every adapter must answer: "what should the screen look like at this time?" -// See the Frame Adapters concept page for the full API. +// Create a GSAP frame adapter +const adapter: FrameAdapter = createGSAPFrameAdapter({ + id: 'my-composition', + fps: 30, + timeline: gsapTimeline, +}); + +// Adapter lifecycle +await adapter.init?.(context); +const durationFrames = adapter.getDurationFrames(); +await adapter.seekFrame(42); +await adapter.destroy?.(); +``` + +## Media Utilities + +```typescript +import { + MEDIA_VISUAL_STYLE_PROPERTIES, + copyMediaVisualStyles, + quantizeTimeToFrame, +} from '@hyperframes/core'; +import type { MediaVisualStyleProperty } from '@hyperframes/core'; + +// Quantize a time value to the nearest frame boundary +const frameTime = quantizeTimeToFrame(5.033, 30); // → 5.033... snapped to frame + +// Copy visual styles between media elements +copyMediaVisualStyles(fromElement, toElement); +``` + +## Picker API + +For element selection in editor UIs: + +```typescript +import type { + HyperframePickerApi, + HyperframePickerBoundingBox, + HyperframePickerElementInfo, +} from '@hyperframes/core'; ``` ## Related Packages diff --git a/docs/packages/engine.mdx b/docs/packages/engine.mdx index a57d4b592..9306b1336 100644 --- a/docs/packages/engine.mdx +++ b/docs/packages/engine.mdx @@ -53,14 +53,16 @@ This approach guarantees [deterministic rendering](/concepts/determinism): the s ## Configuration ```typescript +import { resolveConfig, DEFAULT_CONFIG } from '@hyperframes/engine'; import type { EngineConfig } from '@hyperframes/engine'; -const config: EngineConfig = { - fps: 30, // Frames per second: 24, 30, or 60 - width: 1920, // Output width in pixels - height: 1080, // Output height in pixels - quality: 'standard', // Encoding preset: 'draft', 'standard', or 'high' -}; +// Use defaults +const config = DEFAULT_CONFIG; + +// Or resolve with overrides +const config = resolveConfig({ + // ... custom options +}); ``` ### Quality Presets @@ -81,28 +83,203 @@ const config: EngineConfig = { ## Programmatic Usage -```typescript -import { createEngine } from '@hyperframes/engine'; +The engine uses a session-based API for frame capture: -const engine = createEngine({ +```typescript +import { + createCaptureSession, + initializeSession, + captureFrame, + captureFrameToBuffer, + getCompositionDuration, + closeCaptureSession, +} from '@hyperframes/engine'; + +// 1. Create a capture session +const session = await createCaptureSession({ fps: 30, width: 1920, height: 1080 }); + +// 2. Initialize with a composition +await initializeSession(session, './my-video/index.html'); + +// 3. Get the total duration +const duration = getCompositionDuration(session); + +// 4. Capture frames +const totalFrames = Math.ceil(duration * 30); +for (let i = 0; i < totalFrames; i++) { + // Capture to disk + const result = await captureFrame(session, i); + // result.path, result.captureTimeMs + + // Or capture to buffer (in-memory) + const bufResult = await captureFrameToBuffer(session, i); + // bufResult.buffer, bufResult.captureTimeMs +} + +// 5. Clean up +await closeCaptureSession(session); +``` + +### Browser Management + +```typescript +import { + acquireBrowser, + releaseBrowser, + resolveHeadlessShellPath, + buildChromeArgs, +} from '@hyperframes/engine'; + +// Acquire a browser instance (creates or reuses from pool) +const browser = await acquireBrowser(); + +// Get the Chrome binary path +const chromePath = await resolveHeadlessShellPath(); + +// Release when done +await releaseBrowser(browser); +``` + +### Encoding + +The engine includes FFmpeg encoding utilities: + +```typescript +import { + encodeFramesFromDir, + muxVideoWithAudio, + applyFaststart, + detectGpuEncoder, + ENCODER_PRESETS, +} from '@hyperframes/engine'; + +// Detect GPU encoding support +const gpu = await detectGpuEncoder(); +// gpu: "nvenc" | "videotoolbox" | "vaapi" | null + +// Encode captured frames to video +await encodeFramesFromDir({ framesDir, outputPath, fps: 30, quality: 'standard' }); + +// Mix video with audio tracks +await muxVideoWithAudio({ videoPath, audioTracks, outputPath }); + +// Apply MP4 faststart for streaming +await applyFaststart(outputPath); +``` + +### Streaming Encoder + +For memory-efficient encoding without writing frames to disk: + +```typescript +import { spawnStreamingEncoder } from '@hyperframes/engine'; + +const encoder = await spawnStreamingEncoder({ + outputPath: './output.mp4', fps: 30, width: 1920, height: 1080, }); -// Capture all frames from a composition -const frames = await engine.capture('./my-video/index.html'); +// Feed frames directly to encoder +encoder.writeFrame(frameBuffer); +// ... +const result = await encoder.finalize(); +``` -// Each frame is a pixel buffer (PNG/raw) -for (const frame of frames) { - // Process frames however you need: - // - pipe to FFmpeg - // - save as individual PNGs - // - generate a thumbnail - // - feed into a custom encoder +### Video Frame Extraction + +Extract frames from source video files for injection into the browser: + +```typescript +import { + parseVideoElements, + extractAllVideoFrames, + getFrameAtTime, + createFrameLookupTable, + FrameLookupTable, +} from '@hyperframes/engine'; + +// Parse video elements from HTML +const videos = parseVideoElements(html); + +// Extract all frames from a video +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); +``` + +### Audio Processing + +```typescript +import { parseAudioElements, processCompositionAudio } from '@hyperframes/engine'; + +// Parse audio elements from HTML +const audioElements = parseAudioElements(html); + +// Process and mix all audio tracks +const mixResult = await processCompositionAudio({ audioElements, duration, fps }); +``` + +### Parallel Rendering + +```typescript +import { + calculateOptimalWorkers, + distributeFrames, + executeParallelCapture, + getSystemResources, +} from '@hyperframes/engine'; + +// Check system resources +const resources = getSystemResources(); + +// Calculate optimal worker count +const workers = calculateOptimalWorkers(totalFrames); + +// Distribute frames across workers +const tasks = distributeFrames(totalFrames, workers); + +// Execute parallel capture +const results = await executeParallelCapture(tasks); +``` + +### File Server + +Serve composition files over HTTP for the browser to load: + +```typescript +import { createFileServer } from '@hyperframes/engine'; + +const server = await createFileServer({ root: './my-video', port: 0 }); +// server.url, server.port +// ... use server.url as the composition URL +await server.close(); +``` + +## The `window.__hf` Protocol + +The engine communicates with the browser page via the `window.__hf` protocol. Any page that implements this protocol can be captured by the engine — you are not limited to Hyperframes compositions. + +```typescript +// The page must expose this on window.__hf +interface HfProtocol { + duration: number; // Total duration in seconds + seek(time: number): void; // Seek to a specific time + media?: HfMediaElement[]; // Optional media element declarations } -await engine.close(); +interface HfMediaElement { + elementId: string; // DOM element ID + src: string; // Media source URL + startTime: number; // Start time on timeline + endTime: number; // End time on timeline + mediaOffset?: number; // Playback offset in source + volume?: number; // Volume (0-1) + hasAudio?: boolean; // Whether element has audio +} ``` ## Key Concepts diff --git a/docs/packages/producer.mdx b/docs/packages/producer.mdx index 1750de583..141abc0c1 100644 --- a/docs/packages/producer.mdx +++ b/docs/packages/producer.mdx @@ -54,33 +54,92 @@ The producer orchestrates the full render pipeline: ## Programmatic Usage -```typescript -import { render } from '@hyperframes/producer'; +The producer uses a two-step API: create a render job configuration, then execute it. -const result = await render({ +```typescript +import { createRenderJob, executeRenderJob } from '@hyperframes/producer'; + +const job = createRenderJob({ input: './my-video/index.html', output: './output.mp4', fps: 30, quality: 'standard', }); -console.log(result.duration); // Total render time in ms -console.log(result.frameCount); // Number of frames captured -console.log(result.outputPath); // Absolute path to the output file +const result = await executeRenderJob(job); ``` -### With All Options +### Render Configuration ```typescript -await render({ - input: './my-video/index.html', - output: './output.mp4', - fps: 30, - width: 1920, - height: 1080, - quality: 'high', - docker: true, // Use Docker for deterministic rendering -}); +import type { RenderConfig } from '@hyperframes/producer'; + +const config: RenderConfig = { + fps: 30, // 24, 30, or 60 + quality: 'standard', // 'draft', 'standard', or 'high' + workers: 4, // Parallel render workers (1-8) + useGpu: false, // GPU-accelerated encoding + debug: false, // Debug logging +}; +``` + +### Progress Callbacks + +```typescript +import type { ProgressCallback, RenderStatus } from '@hyperframes/producer'; + +const onProgress: ProgressCallback = (status: RenderStatus) => { + console.log(`Status: ${status}`); + // Statuses: "queued" | "preprocessing" | "rendering" | "encoding" + // | "assembling" | "complete" | "failed" | "cancelled" +}; +``` + +### Cancellation + +```typescript +import { RenderCancelledError } from '@hyperframes/producer'; + +try { + await executeRenderJob(job); +} catch (err) { + if (err instanceof RenderCancelledError) { + console.log(`Cancelled: ${err.reason}`); + // reason: "user_cancelled" | "timeout" | "aborted" + } +} +``` + +## HTTP Server + +The producer includes a built-in HTTP server for running as a rendering service: + +```typescript +import { startServer } from '@hyperframes/producer/server'; + +await startServer({ port: 8080 }); +``` + +### Server Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| `POST` | `/render` | Blocking render — returns JSON result | +| `POST` | `/render/stream` | Streaming render with Server-Sent Events | +| `POST` | `/lint` | Lint a composition for issues | +| `GET` | `/health` | Health check | +| `GET` | `/outputs/:token` | Download a rendered MP4 | + +For custom server integration, use the lower-level handlers: + +```typescript +import { createRenderHandlers, createProducerApp } from '@hyperframes/producer/server'; + +// Get individual request handlers +const handlers = createRenderHandlers(options); + +// Or get a full Hono app +const app = createProducerApp(options); ``` ## Docker Rendering @@ -89,10 +148,7 @@ For deterministic output, the producer can render inside a Docker container with ```bash # Via the CLI (recommended) -npx hyperframes render --docker -o output.mp4 - -# Via the producer API -await render({ input: './index.html', output: './out.mp4', docker: true }); +npx hyperframes render --docker --output output.mp4 ``` @@ -123,6 +179,26 @@ GPU encoding is automatically used when available. To check your system's capabi npx hyperframes doctor ``` +## Additional Exports + +The producer also re-exports key engine functionality for convenience: + +| Export | Description | +|--------|-------------| +| `createCaptureSession()` | Create a frame capture session | +| `initializeSession()` | Initialize session with a composition | +| `captureFrame()` / `captureFrameToBuffer()` | Capture individual frames | +| `closeCaptureSession()` | Clean up a capture session | +| `getCompositionDuration()` | Get total composition duration | +| `getCapturePerfSummary()` | Get capture performance metrics | +| `createFileServer()` | Create an HTTP file server for serving assets | +| `createVideoFrameInjector()` | Create a video frame injector for page | +| `resolveConfig()` / `DEFAULT_CONFIG` | Producer configuration | +| `createConsoleLogger()` / `defaultLogger` | Logging utilities | +| `quantizeTimeToFrame()` | Convert time to frame boundary | +| `resolveRenderPaths()` | Resolve render directory paths | +| `prepareHyperframeLintBody()` / `runHyperframeLint()` | Linting utilities | + ## Regression Testing The producer includes a regression harness for comparing render output against golden baselines. This is useful for catching visual regressions when changing the runtime, engine, or rendering pipeline. diff --git a/docs/packages/studio.mdx b/docs/packages/studio.mdx index 61b5456cc..5326fc98e 100644 --- a/docs/packages/studio.mdx +++ b/docs/packages/studio.mdx @@ -45,7 +45,137 @@ bun run dev bun run --filter @hyperframes/studio dev ``` -The studio starts at `http://localhost:3000` by default. +## Package Exports + +The studio has two entry points: + +| Import | Description | +|--------|-------------| +| `@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). + +## Components + +### Layout + +```typescript +import { NLELayout, NLEPreview, CompositionBreadcrumb } from '@hyperframes/studio'; +import type { CompositionLevel } from '@hyperframes/studio'; + +// Main NLE (Non-Linear Editor) layout container + + {/* Preview, timeline, and editor panels */} + + +// Preview panel + + +// Breadcrumb navigation for nested compositions + +``` + +### Player & Timeline + +```typescript +import { + Player, + PlayerControls, + Timeline, + PreviewPanel, + AgentActivityTrack, +} from '@hyperframes/studio'; +import type { AgentActivity, TimelineElement, ActiveEdits } from '@hyperframes/studio'; + +// Embed the preview player + + +// Playback controls (play, pause, seek, frame-step) + + +// Timeline editor with scrubber + + +// Preview display area + + +// Activity visualization track (for agent workflows) + +``` + +### Editor Components + +```typescript +import { SourceEditor, PropertyPanel, FileTree } from '@hyperframes/studio'; + +// Code editor (CodeMirror-based) for HTML, CSS, and JavaScript + + +// Property inspector for selected elements + + +// Project file browser + +``` + +### Full Application + +```typescript +import { StudioApp } from '@hyperframes/studio'; + +// The complete studio application (wraps all components) + +``` + +## Hooks + +### `useTimelinePlayer` + +Manages player state and playback control: + +```typescript +import { useTimelinePlayer } from '@hyperframes/studio'; + +const player = useTimelinePlayer(); +// player.play(), player.pause(), player.seek(time), player.stepForward(), player.stepBackward() +``` + +### `usePlayerStore` + +Zustand store for player state: + +```typescript +import { usePlayerStore, liveTime, formatTime } from '@hyperframes/studio'; + +const store = usePlayerStore(); +// Access current time, duration, playing state, etc. + +// Format time for display +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: + +```typescript +import { useElementPicker } from '@hyperframes/studio'; + +const picker = useElementPicker(); +// picker.selectedElement, picker.selectElement(id), picker.clearSelection() +``` ## Features @@ -91,29 +221,20 @@ The studio is a React application with the following structure: 4. **File watcher** — a development server (Vite-based) watches your project files and triggers hot module replacement when changes are detected. -## Embedding in Your Own Application +## Tailwind CSS Preset -If you are building a product that includes a composition editor, you can use the studio's components directly: +The studio exports a Tailwind CSS preset for consistent styling: ```typescript -import { Player, Timeline } from '@hyperframes/studio'; +// tailwind.config.ts +import studioPreset from '@hyperframes/studio/tailwind-preset'; -// Embed the preview player - - -// Embed the timeline view - +export default { + presets: [studioPreset], + // ... your config +}; ``` - - The studio depends on `@hyperframes/core` for parsing and runtime injection. You do not need to install core separately — it is included as a dependency. - - ## Related Packages diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index 7eca13ebd..efed5b703 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -12,15 +12,15 @@ A 1920x1080 video with an animated title that fades in from above — rendered t ## Prerequisites - - Hyperframes requires Node.js 20 or later. Check your version: + + Hyperframes requires Node.js 22 or later. Check your version: ```bash node --version ``` ```bash Expected output - v20.11.0 # or any version >= 20 + v22.0.0 # or any version >= 22 ``` @@ -58,36 +58,46 @@ A 1920x1080 video with an animated title that fades in from above — rendered t ```bash - npx create-hyperframe my-video + npx hyperframes init my-video --template blank cd my-video ``` - ```bash Expected output - ✔ Created my-video/ - ✔ index.html - ✔ assets/ - Done. Run `npx hyperframes dev` to preview. + The CLI is non-interactive by default — pass `--template` to select a template. For interactive mode with prompts and menus, add `--human-friendly`: + + ```bash + npx hyperframes init --human-friendly ``` - This generates the following project structure: + See [Templates](/guides/templates) for all available templates. + + This generates a project structure like: + - + + - + | Path | Purpose | |------|---------| + | `meta.json` | Project metadata (name, ID, creation date) | | `index.html` | Root composition — your video's entry point | | `compositions/` | Sub-compositions loaded via `data-composition-src` | | `assets/` | Media files (video, audio, images) | + + If you have a source video, pass it with `--video` for automatic transcription and captions: + + ```bash + npx hyperframes init my-video --template warm-grain --video ./intro.mp4 + ``` @@ -95,12 +105,7 @@ A 1920x1080 video with an animated title that fades in from above — rendered t npx hyperframes dev ``` - ```bash Expected output - ✔ Hyperframes dev server running - → http://localhost:3000 - ``` - - Open [http://localhost:3000](http://localhost:3000) to see the live preview. Edits to `index.html` reload automatically. + This starts the Hyperframes Studio and opens your composition in the browser. Edits to `index.html` reload automatically. The dev server supports hot reload — save your HTML file and the preview updates instantly, no manual refresh needed. @@ -145,7 +150,7 @@ A 1920x1080 video with an animated title that fades in from above — rendered t ```bash - npx hyperframes render -o output.mp4 + npx hyperframes render --output output.mp4 ``` ```bash Expected output @@ -162,8 +167,8 @@ A 1920x1080 video with an animated title that fades in from above — rendered t | Dependency | Required | Notes | |-----------|----------|-------| -| **Node.js** 20+ | Yes | Runtime for CLI and dev server | -| **bun** or npm | Yes | Package manager (bun recommended) | +| **Node.js** 22+ | Yes | Runtime for CLI and dev server | +| **npm** or bun | Yes | Package manager | | **FFmpeg** | Yes | Video encoding for local renders | | **Docker** | No | Optional — for deterministic, reproducible renders | @@ -177,7 +182,7 @@ A 1920x1080 video with an animated title that fades in from above — rendered t Add fade, slide, scale, and custom animations to your videos - Start from built-in templates like title-card and video-edit + Start from built-in templates like Warm Grain and Swiss Grid Explore render options: quality presets, Docker mode, and GPU encoding