引擎包提供低级视频捕获管道:它在无头 Chrome 中加载 HTML 页面,独立查找每个帧,并使用 Chrome 的 HeadlessExperimental.beginFrame API 捕获像素缓冲区。该层使HyperFrames渲染具有确定性。
npm install @hyperframes/engine
何时使用
大多数用户不应该直接使用引擎。 请使用 CLI (npx hyperframes render) 或 生产者 包 - 它们会为您处理运行时注入、音频混合和编码。
当您需要时使用 @hyperframes/engine:
构建自定义渲染管道,完全控制帧捕获
将HyperFrames捕获集成到现有视频处理系统中
捕获单个帧(例如缩略图或精灵表),无需编码为视频
实现自定义编码后端(不是 FFmpeg)
如果您愿意,请使用不同的包:
将 HTML 合成渲染为完成的 MP4 或 WebM — 使用 生产者 或 CLI
在浏览器中预览合成 — 使用 CLI 或 studio
Lint 或解析 HTML 组合 — 使用 core
它是如何运作的
该引擎实现了一个与屏幕录制根本不同的 寻找和捕获 循环:
启动无头 Chrome
该引擎启动 chrome-headless-shell,这是一个最小的无头 Chrome 二进制文件,针对通过 Chrome DevTools 协议 (CDP) 进行编程控制进行了优化。
加载构图
您的 HTML 组合将加载到浏览器页面中。注入 Hyperframes 运行时来管理时间线搜索。
寻找每一帧
对于视频中的每一帧(例如,30fps 的 30 秒视频为 900 帧),引擎调用 renderSeek(time) 将合成推进到准确的时间戳。不涉及挂钟——每个框架都是独立定位的。
通过 BeginFrame 捕获
Chrome 的 HeadlessExperimental.beginFrame API 将合成器输出捕获为像素缓冲区。这会产生像素完美的帧,没有任何屏幕录制伪影。
移交帧
捕获的帧缓冲区被传递给消费者 - 通常是 FFmpeg(通过生产者)用于编码为 MP4,但您可以提供自己的消费者。
这种方法保证了确定性渲染 :相同的 HTML 始终生成相同的视频,无论系统负载或计时如何。
import { resolveConfig , DEFAULT_CONFIG } from '@hyperframes/engine' ;
import type { EngineConfig } from '@hyperframes/engine' ;
// Use defaults
const config = DEFAULT_CONFIG ;
// Or resolve with overrides
const config = resolveConfig ({
// ... custom options
});
质量预设
预设 使用案例 速度 draft开发过程中快速迭代 最快 standard制作渲染具有良好的质量/速度平衡 缓和 high最终交付,最高品质 最慢
FPS 选项
FPS 使用案例 24电影般的外观,更小的文件大小 30标准网络视频,平衡性好 60流畅的动作、UI 动画、屏幕录制
程序化使用
该引擎使用基于会话的 API 进行帧捕获:
import {
createCaptureSession ,
initializeSession ,
captureFrame ,
captureFrameToBuffer ,
getCompositionDuration ,
closeCaptureSession ,
} from '@hyperframes/engine' ;
// 1. Create a capture session
const session = await createCaptureSession ({ fps: { num: 30 , den: 1 }, 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 );
浏览器管理
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 );
该引擎包括 FFmpeg 编码实用程序,支持 MP4 (h264) 和 WebM(带 alpha 的 VP9):
import {
encodeFramesFromDir ,
muxVideoWithAudio ,
applyFaststart ,
detectGpuEncoder ,
getEncoderPreset ,
ENCODER_PRESETS ,
} from '@hyperframes/engine' ;
// Get format-aware encoder settings
const mp4Preset = getEncoderPreset ( 'standard' , 'mp4' );
// { codec: "h264", pixelFormat: "yuv420p", preset: "medium", quality: 23 }
const webmPreset = getEncoderPreset ( 'standard' , 'webm' );
// { codec: "vp9", pixelFormat: "yuva420p", preset: "good", quality: 23 }
// Encode captured frames to video
await encodeFramesFromDir ( framesDir , 'frame_%06d.png' , outputPath , {
fps: { num: 30 , den: 1 },
... webmPreset ,
});
// Mix video with audio (uses Opus for WebM, AAC for MP4)
await muxVideoWithAudio ( videoPath , audioPath , outputPath );
// Apply MP4 faststart for streaming (no-op for WebM)
await applyFaststart ( inputPath , outputPath );
// Detect GPU encoding support
const gpu = await detectGpuEncoder ();
// gpu: "nvenc" | "videotoolbox" | "vaapi" | "qsv" | "amf" | null
WebM 与 VP9 Alpha
为透明度进行编码时,请将 format: "webm" 与 getEncoderPreset() 结合使用。这配置:
VP9 编解码器 (libvpx-vp9) 具有支持 alpha 的 yuva420p 像素格式
-auto-alt-ref 0 和 alpha_mode=1 元数据用于正确的 alpha 编码
-row-mt 1 用于多线程 VP9 编码
复用步骤中的 Opus 音频 (而不是 MP4 的 AAC)
流媒体编码器
对于无需将帧写入磁盘的内存高效编码:
import { spawnStreamingEncoder } from '@hyperframes/engine' ;
const encoder = await spawnStreamingEncoder ({
outputPath: './output.mp4' ,
fps: { num: 30 , den: 1 },
width: 1920 ,
height: 1080 ,
});
// Feed frames directly to encoder
encoder . writeFrame ( frameBuffer );
// ...
const result = await encoder . finalize ();
视频帧提取
从源视频文件中提取帧以注入浏览器:
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 );
音频处理
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 });
并行渲染
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 );
文件服务器
通过 HTTP 提供合成文件以供浏览器加载:
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 ();
HDR API
该引擎导出两层 HDR 支持:颜色空间实用程序 ,用于对源进行分类并配置 FFmpeg 编码器,以及 WebGPU 读回运行时 ,用于将 CSS 动画 DOM 直接捕获到 HDR 中。
对于端到端 HDR 渲染(合成为 HDR10 MP4 的 HDR 视频和图像源),请使用 生产者 或具有 HDR 自动检测功能的 CLI 渲染管道 / --hdr / --sdr — 请参阅 HDR 渲染 。以下 API 用于自定义集成。
色彩空间实用程序
import {
isHdrColorSpace ,
detectTransfer ,
analyzeCompositionHdr ,
getHdrEncoderColorParams ,
DEFAULT_HDR10_MASTERING ,
} from '@hyperframes/engine' ;
import type { HdrTransfer , HdrEncoderColorParams , HdrMasteringMetadata } from '@hyperframes/engine' ;
// Classify a single source from its ffprobe color space
isHdrColorSpace ( colorSpace ); // boolean — true for BT.2020 / PQ / HLG
detectTransfer ( colorSpace ); // 'pq' | 'hlg' (gate on isHdrColorSpace first)
// Pick the dominant transfer across many sources
analyzeCompositionHdr ([ cs1 , cs2 ]); // { hasHdr, dominantTransfer: 'pq' | 'hlg' | null }
// Build the FFmpeg color params + HDR10 static metadata for x265
const params = getHdrEncoderColorParams ( 'pq' );
// {
// colorPrimaries: 'bt2020',
// colorTrc: 'smpte2084',
// colorspace: 'bt2020nc',
// pixelFormat: 'yuv420p10le',
// x265ColorParams: 'colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:master-display=...:max-cll=1000,400',
// mastering: { masterDisplay: '...', maxCll: '1000,400' },
// }
getHdrEncoderColorParams 始终包含颜色标记和 HDR10 静态元数据(控制显示 + 内容亮度级别)。如果没有该元数据,下游播放器会将该文件视为 SDR BT.2020,并且会错误地进行色调映射。如果您测量了每个内容的值,则传递自定义 HdrMasteringMetadata ;否则,保守的 DEFAULT_HDR10_MASTERING 默认值与大多数 HDR10 分级套件标记内容的方式相匹配。
WebGPU HDR DOM 捕获
为了将 CSS 动画 DOM 直接捕获到 HDR(不涉及 FFmpeg 源),引擎公开了一个单独的 WebGPU 管道:
import {
launchHdrBrowser ,
buildHdrChromeArgs ,
initHdrReadback ,
uploadAndReadbackHdrFrame ,
float16ToPqRgb ,
} from '@hyperframes/engine' ;
// Launch headed Chrome with WebGPU enabled
const { browser , page } = await launchHdrBrowser ({ width: 1920 , height: 1080 });
// Inject the WebGPU readback runtime
const ok = await initHdrReadback ( page , 1920 , 1080 );
// For each frame: upload float16 pixels, read back float16 RGBA
const { rgba16 , bytesPerRow } = await uploadAndReadbackHdrFrame ( page , float16Base64 );
// Convert linear float16 → PQ-encoded 16-bit RGB suitable for piping into ffmpeg/x265
const pqRgb = float16ToPqRgb ( rgba16 , width , height , bytesPerRow );
此路径需要 headed Chrome 和 --enable-unsafe-webgpu — WebGPU 在 chrome-headless-shell 中不可用。默认的 HDR 感知渲染管道(通过 FFmpeg 从源中提取 HDR 像素并在 Node 中进行合成)不 使用它。仅将其用于需要 CSS 动画驱动 HDR 像素输出的高级自定义管道。
window.__hf 协议
引擎通过 window.__hf 协议与浏览器页面通信。任何实现此协议的页面都可以被引擎捕获 - 您不仅限于超框架组合。
// 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
}
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
}
关键概念
开始帧渲染
传统的屏幕捕获以挂钟速度记录 - 如果您的系统负载过重,就会丢帧。该引擎使用 Chrome 的 HeadlessExperimental.beginFrame 显式推进合成器,按需生成每一帧。这意味着:
无丢帧 — 捕获每一帧
无时间依赖性 — 60 秒的视频不需要 60 秒来捕获
像素完美输出 — 合成器生成要显示的精确像素
有关如何实现确定性输出的更多信息,请参阅确定性渲染 。
寻求合同
该引擎依赖于 Hyperframes 运行时的 renderSeek(time) 函数。调用时,renderSeek:
暂停所有 GSAP 时间表
寻找每个时间线的确切时间戳
更新所有媒体元素(视频、音频)以匹配
根据 data-start 和 data-duration 安装/卸载剪辑
这个契约使得逐帧捕捉成为可能——每一帧都是该时间点合成的完整、独立的快照。
Chrome 要求
该引擎需要 chrome-headless-shell,它在您安装软件包时包含在内。它使用固定的 Chrome 版本来确保跨环境的一致渲染。要获得完全确定性的输出(包括字体),请通过 生产者 使用 Docker 模式。
相关套餐
制片人 通过运行时注入、FFmpeg 编码和音频混合来包装引擎,以实现完整的 MP4 输出。
命令行界面 最简单的渲染方法——在后台调用生产者(和引擎)。
工作室 用于在使用引擎渲染合成之前构建合成的可视化编辑器。