mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-14 18:01:20 +08:00
baa1627dce
The render bridge previously overwrote `window.__hf` wholesale at end-of-body, clobbering anything written during user `<script>` execution. Libraries such as `@hyperframes/shader-transitions` populate `window.__hf.transitions` inside their `init()` call, so the engine never saw a transition map and HDR compositing fell back to plain DOM layers. Two changes restore the contract: 1. Inject HF_EARLY_STUB at the very start of `<head>` so `window.__hf` exists before any other script runs. User libraries can now safely write to it during initialisation. 2. HF_BRIDGE_SCRIPT now patches the existing `__hf` object (defining `duration` as a getter and assigning `seek`) instead of replacing it, preserving any fields the page already populated. Adds a regression test that simulates the real injection order — early stub, authored page script writing `__hf.transitions`, bridge script — and asserts both `transitions` and the bridge-installed `seek`/`duration` are present afterwards. Made-with: Cursor
@hyperframes/producer
Full HTML-to-video rendering pipeline: capture frames with Chrome's BeginFrame API, encode with FFmpeg, mix audio — all in one call.
Install
npm install @hyperframes/producer
Requirements: Node.js >= 22, Chrome/Chromium (auto-downloaded), FFmpeg
Usage
Render a video
import { createRenderJob, executeRenderJob } from "@hyperframes/producer";
const job = createRenderJob({
inputPath: "./my-composition.html",
outputPath: "./output.mp4",
width: 1920,
height: 1080,
fps: 30,
});
const result = await executeRenderJob(job, (progress) => {
console.log(`${Math.round(progress.percent * 100)}%`);
});
console.log(result.outputPath); // ./output.mp4
Run as an HTTP server
The producer can also run as a render server, accepting render requests over HTTP:
import { startServer } from "@hyperframes/producer";
await startServer({ port: 8080 });
// POST /render with a RenderConfig body
Configuration
RenderConfig controls the render pipeline:
| Option | Default | Description |
|---|---|---|
inputPath |
— | Path to the HTML composition |
outputPath |
— | Output video file path |
width |
1920 | Frame width in pixels |
height |
1080 | Frame height in pixels |
fps |
30 | Frames per second (24, 30, or 60) |
quality |
"standard" |
Encoder preset ("draft", "standard", "high") |
How it works
- Serve — spins up a local file server for the HTML composition
- Capture — opens the page in headless Chrome, seeks frame-by-frame via
HeadlessExperimental.beginFrame, captures screenshots - Encode — pipes frames through FFmpeg (with GPU encoder detection and chunked concat)
- Mix — extracts
<audio>elements and mixes them into the final video - Finalize — applies faststart for streaming-friendly MP4
Documentation
Full documentation: hyperframes.heygen.com/packages/producer
Related packages
@hyperframes/core— types, parsers, frame adapters@hyperframes/engine— lower-level capture and encode primitiveshyperframes— CLI