@hyperframes /制作人
完整的html到视频渲染管道:用Chrome的BeginFrame API捕获帧,用FFmpeg编码,混合音频-都在一个调用中。
安装
npm install @hyperframes/producer
要求: Node.js >= 22, Chrome/Chromium(自动下载),FFmpeg
使用
渲染视频
import { createRenderJob, executeRenderJob } from "@hyperframes/producer";
const job = createRenderJob({
fps: 30,
quality: "standard",
});
await executeRenderJob(job, "./my-project", "./output.mp4", (currentJob) => {
console.log(`${Math.round(currentJob.progress)}%`);
});
作为HTTP服务器运行
生产者也可以作为渲染服务器运行,通过HTTP接受渲染请求:
import { startServer } from "@hyperframes/producer";
await startServer({ port: 8080 });
// POST /render or /render/stream with projectDir, html, or previewUrl (public HTTPS only) and render options
两个HTTP路由都接受可选 pageMotionBlur: "off" 禁用已创建页面
动态模糊。省略它以保持组合的行为。其他显式值
在渲染开始前被拒绝。这是分开的发动机子框架
motionBlur 抽样。
配置
RenderConfig 控制渲染管道:
| 选项 | 默认的 | 描述 |
|---|---|---|
entryFile | index.html | 项目目录中的条目组合。其生成的尺寸设置画布的大小。 |
fps | 要求 | 帧速率为整数或精确值 { num, den } 理性的。 |
quality | 要求 | 编码器预设("draft", "standard", "high")。 |
pageMotionBlur | 作者设置 | 集 "off" 禁用页面动态模糊;省略以保留撰写的行为。 |
format | "mp4" | 输出容器- "mp4", "webm", "mov", "gif", "png-sequence",或者 "hls". 看到 透明视频输出 和 HLS输出 下面。 |
hlsSegmentSeconds | 4 | 以秒为单位的HLS目标段长度。对于其他格式忽略。 |
videoFrameFormat | "auto" | 源视频帧提取格式 "auto", "jpg",或者 "png"。使用 "png" 用于UI录制,屏幕截图和彩色敏感源视频。 |
透明视频输出
生成器可以将HTML组合呈现为带有 真α通道 -不是色度键。当你设置时,渲染不透明MP4的相同构图会渲染可分层的叠加 format.
format | 编解码/像素格式 | α | 音频 | 用例 |
|---|---|---|---|---|
"mp4" (默认) | H.264 (yuv420p)或H.265 + HDR10 | 否 | AAC格式 | 流媒体,社交,默认交付 |
"webm" | VP9 + yuva420p | 真正的α | 作品 | 网页播放(<video> 在背景);支持Chrome, Edge, Firefox |
"mov" | ProRes 4444 + yuva444p10le | 真正的α | AAC格式 | 编辑器摄取(Premiere, Final Cut Pro,达芬奇Resolve) |
"png-sequence" | 目录中的RGBA png编号 | 无损的α | 双轮马车 audio.m4a | After Effects / Nuke / Fusion,或者在编码前对帧进行后处理的管道 |
"hls" | H.264 (yuv420p)在MPEG-TS | 否 | AAC引渡 | 视频点播流-见 HLS输出 |
例子
import { createRenderJob, executeRenderJob } from "@hyperframes/producer";
const job = createRenderJob({
fps: 30,
quality: "standard",
format: "webm", // "mp4" | "webm" | "mov" | "png-sequence"
});
await executeRenderJob(job, "./my-project", "./output.webm");
“透明背景”在这里意味着什么
制作人捕获Chrome屏幕截图与页面背景强制透明(html, body, [data-composition-id] { background: transparent !important })和CDP默认的背景覆盖设置为RGBA 0,0,0,0。捕获的png携带一个真正的alpha通道,该通道被端到端保存:
- VP9 (
webm)的编码为-pix_fmt yuva420p,-auto-alt-ref 0,-cpu-used 4默认情况下,和alpha_mode=1元数据。调整速度/质量的权衡PRODUCER_VP9_CPU_USED(-8来8)或本地命令行--vp9-cpu-used. - prost4444 (
mov)使用-pix_fmt yuva444p10le带一个单独的平面。Chrome的RGBA捕获,包括alpha,是每个通道8位;10位像素格式不增加捕获精度。 - PNG序列写入时不需要重新编码(零填充)
frame_NNNNNN.png)。
这不是色度键控。没有绿色/蓝色背景要删除,也没有“键”公差来调整-在浏览器中透明的像素在输出中是透明的。
警告
- Linux + alpha强制截图。 Chrome的BeginFrame合成器(Linux headless-shell上默认的确定性捕获路径)不保留alpha;编曲家又回到
Page.captureScreenshot,每帧速度较慢。macOS和Windows已经默认使用截图模式,所以它们不受影响。 - 不支持HDR + alpha。 设置
hdr: true与具有alpha功能的格式一起记录警告并回落到SDR。使用format: "mp4"用于HDR10输出。 png-sequence不生成单个混合文件。 当合成包含音频元素时audio.m4asidecar是写在png旁边的outputPath.- Safari + WebM alpha是不完整的。 对于广泛的浏览器播放的alpha视频,船
format: "mov"到您的编辑器,并重新编码为您的发行版目标支持的编解码器。
创建透明的组合
不要在HTML中绘制全屏背景。默认的主体背景被自动覆盖为透明-任意 body { background: ... }, #root { background: ... },或者 [data-composition-id] { background: ... } 规则在alpha渲染期间被强制覆盖。保留内部元素(卡片、场景、组件)的背景。
HLS输出
format: "hls" 封装相同的H.264 + AAC编码 mp4 作为HLS视频点播
流。 outputPath 是一个 目录:
master.m3u8 # references both renditions
video.m3u8 # video media playlist
video_00000.ts # MPEG-TS segments, one IDR frame at the start of each
audio.m3u8 # written only when the composition has audio
audio_00000.ts
const job = createRenderJob({
fps: 30,
quality: "standard",
format: "hls",
hlsSegmentSeconds: 4,
});
await executeRenderJob(job, "./my-project", "./renders/stream");
分段就是 hlsSegmentSeconds 长,除了最后一个:编码器的GOP
被锁定为 round(fps × hlsSegmentSeconds) 这样包装盒就能过关了
stream-copy (-c copy),仍然在关键帧上剪切。没有第二种编码。
约束:
- 特别提款权。
hdrMode: "force-hdr"被拒绝;HDR10需要fMP4 细分和HEVC。使用format: "mp4"HDR。 - 仅软件编码器。
useGpu: true被拒绝- GPU编码器忽略 固定长度片段所依赖的强制关键帧锁。 - 在分布式呈现中不可用,包括Lambda和Cloud Run。
- MPEG-TS不携带移动族元数据,因此呈现的来源标记是写入的 到MP4输出是缺席。
分布式渲染
对于单个机器来说太大的渲染,生产者提供了一组公共的分布式渲染原语。它们是本地文件路径上的纯函数——网络和编排存在于适配器包中(Temporal、AWS Lambda + Step functions、Cloud Run Jobs、K8s Jobs)。
对于新的集成,建议使用Plan v2。它发布一个不可变的 清单加上内容寻址的工件,并且只具体化每个工人的 声明依赖性:
import { planV2, renderChunkV2, assembleV2 } from "@hyperframes/producer/distributed";
// Controller-side: produce a v2 manifest + local content-addressed store.
const planResult = await planV2(
projectDir,
{ fps: 30, width: 1920, height: 1080, format: "mp4" },
"/tmp/plan-v2",
);
const chunk = await renderChunkV2("/tmp/plan-v2", 0, "/tmp/chunks/0.mp4");
// Controller-side: stitch chunks into the final deliverable.
await assembleV2("/tmp/plan-v2", ["/tmp/chunks/0.mp4", "/tmp/chunks/1.mp4"], "/tmp/output.mp4");
云适配器应该使用 planV2WithPublisher() 所以艺术品发布了
直接到对象存储。遗留 plan() / renderChunk() /
assemble() v1布局仍然受支持,云sdk仍然可以解释
为了向后兼容,省略了v1协议。
活动函数和它们的结果类型也被重新导出 @hyperframes/producer 因此,固定主包的调用者不需要单独的子路径导入。支持格式: mp4 特别提款权, mov ProRes 4444和 png-sequence。webm和HDR mp4行程类型 FormatNotSupportedInDistributedError -使用进程内渲染器(executeRenderJob)。
它是如何工作的
- 服务 -为HTML组合启动本地文件服务器
- 捕获 -在无头Chrome中打开页面,通过逐帧搜索
HeadlessExperimental.beginFrame(或Page.captureScreenshot用于透明/非linux渲染),捕获屏幕截图 - 编码 -管道帧通过FFmpeg(与GPU编码器检测和分块连接)。跳过的
format: "png-sequence". - 混合 ——提取
<audio>元素并将它们混合到最后的视频中。为png-sequence在美国,音频被写成anaudio.m4a双轮马车。 - 完成 -适用于流友好的MP4快速启动(无操作的WebM, MOV,和
png-sequence). 为hls,流媒体将编码复制到播放列表和MPEG-TS片段中。
每一步都在哪里
executeRenderJob 在 src/services/renderOrchestrator.ts 运行阶段
src/services/render/stages/,顺序如下:
compileStage.ts,probeStage.ts,extractVideosStage.ts,audioStage.tssrc/services/render/captureCost.ts计算工人数量 (runCaptureCalibration,然后resolveRenderWorkerCount)createCapturePlan在src/services/render/capturePlan.ts选择捕获 类型:流式,磁盘,分段或HDR分层- 获取:
captureStreamingStage.ts,captureSegmentedStage.ts和captureHdrStage.ts捕获时进行编码;磁盘捕获(captureStage.ts) 随后编码为encodeStage.ts assembleStage.ts,除了PNG序列和GIF,它们是编写的 直接
工作的 producerConfig 现在时使用;否则 resolveConfig 在
packages/engine/src/config.ts 构建它。捕获,编码和浏览器
原语是引擎服务(参见 packages/engine/README.md)。
文档
完整的文档: hyperframes.heygen.com/packages/producer
相关的包
@hyperframes/core-类型,解析器,帧适配器@hyperframes/engine-低级捕获和编码原语hyperframes- - - - - - CLI