WebVideoCreator
🌈 A framework for rendering web animations into videos. It's implemented based on Node.js + Puppeteer + Chrome + FFmpeg, utilizing the latest browser APIs.
Install / Use
/learn @Vinlic/WebVideoCreatorREADME
简介
🌈 WebVideoCreator(简称WVC)是一个将Web动画渲染为视频的框架,基于 Node.js + Puppeteer + Chrome + FFmpeg 实现,它执行确定性的渲染,准确的以目标帧率捕获任何可在HTML5播放动画(CSS3动画/SVG动画/Lottie动画/GIF动画/APNG动画/WEBP动画)以及任何基于时间轴使用RAF驱动的动画(anime.js是一个不错的选择 :D),当然您也可以调皮的使用setInterval或者setTimeout来控制动画,支持导出和嵌入mp4或透明通道的webm视频,还支持转场合成、音频合成与字体加载等功能。让我们快速开始 🍻。
WVC为您酷炫的动画页面创造了一个虚拟时间环境🕒(也许可以想象成是一个《楚门的世界》),它的主要职责是将一个 不确定性渲染的环境 转化到 确定性渲染的环境。
这一切的前提由Chrome提供的确定性渲染模式和无头实验API支持:HeadlessExperimental.beginFrame,这是创新的实验性功能 🧪。
答疑交流QQ群🐧:752693580
<br>特性
- 基于Node.js开发,使用非常简单,易于扩展和开发。
- 视频处理速度非常快,最快5分钟视频可在1分钟内完成渲染,查看性能提示获得最佳性能。
- 支持单幕和多幕视频渲染合成,多幕视频可应用转场效果。
- 支持分块视频合成,可以将分块分发到多个设备上渲染回传再合成为多幕视频,大幅降低长视频渲染耗时。
- 支持并行多个视频渲染合成任务,充分利用系统资源。
- 支持嵌入或导出支持透明通道的webm格式视频,可以用于合成数字人。
- API支持进行分布式渲染封装,只需对WVC进行一些封装即可将大量视频分块分发到多个设备渲染并最终取回合并输出
- 支持使用GPU加速渲染和合成,可以显著的降低视频渲染耗时。
- 支持在Windows和Linux平台部署运行,Mac上需要开启兼容渲染模式。
有什么用?
WVC实现对Web页面任意动画的逐帧完美捕获,它可以最大化降低实现所见即所得的成本,它作为渲染后端目前发掘了以下用途:
📊 数据可视化视频渲染:结合ECharts等图表库在Web上实现图表动画并用WVC捕获为视频,比如抖音和视频号常见的动态排行榜视频,配合爬虫采数据更佳。
👩🏫 数字人视频渲染:AIGC概念火爆,各种数字分身搬上了荧幕,WVC支持在页面中使用透明通道视频或蒙版视频,可以在动画基础上配上数字人获得更好的视觉效果。
🎨 内容创作视频渲染:您可以设计一个简单的前端动画编辑和预览器来满足一些内容创作需求,使用WVC作为后端获得所见即所得的视频效果。
🎮️ 游戏或用户操作回放视频渲染:与基于Web开发的游戏或应用结合,云上将回放捕获为视频提供给用户可方便分享和二次剪辑。
更多应用场景等待您的发掘,有好的想法记得提issue 🙋♀️...
相比录屏工具的优势?
💯 完美捕获:浏览器的帧合成器默认存在节流策略以减少资源消耗,当绘制大量复杂图形或系统负载加大时会导致Web动画出现跳帧、掉帧、延缓等问题,如果使用录屏工具将难以确保每一帧都被正确捕获,而WVC接管了时间流速,能够决定下一帧什么时候绘制到画面。
🎞️ 并行渲染:录屏工具通常无法同时捕获多个Tab页的动画内容,但WVC可以在多个页面中并行捕获动画并最终合成这些分块为一个长视频,分段之间还支持合成转场。
🦾 可自动化:录屏工具需要人工操作,基于WVC可以使用一套Web动画模板结合数据爬虫+定时任务,自动的产出视频。
🧩 快速集成:录屏工具难以集成,WVC是基于Node.js开发的NPM包,可以很快的进行后端集成,有的开发者用于将游戏回放捕获为视频。
<br>视频DEMO
我们还缺少动画设计师,如果您热衷于开源事业欢迎加入我们😆。
在这里查看所有DEMO:渲染示例页面 🤗
<img src="assets/demo.gif"/> <br>支持的动画库
理论上所有的Web动画/图形库都能够在WVC环境正常运行,以下仅列出我已验证可用的库:
Anime.js / GSAP / D3.js / Three.js / Echart / Lottie-Web / PixiJS / Animate.css / Mo.js / Tween.js
需要注意的是,如果您手动使用RAF驱动动画,请确保从回调中接收timestamp参数设置动画的进度到该时间点,否则可能出现帧率不同步。
<br>快速开始
安装
# 从NPM安装WebVideoCreator
npm i web-video-creator
如遇到ffmpeg-static下载失败,请先设置环境变量:FFMPEG_BINARIES_URL=https://cdn.npmmirror.com/binaries/ffmpeg-static
创建本地服务器
WVC需要从Web页面中捕获动画,您可以在本地创建一个临时的Web服务器来提供静态页面服务,方便接下来的测试,使用live-server是最简单的方式之一,如果您已经有静态页面可跳过这个步骤。
# 从NPM全局安装live-server
npm i -g live-server
# 启用Web服务
live-server
创建一个测试页面到Web服务根路径,以下html内容展示一个自动旋转的红色三角形svg动画。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>测试页面</title>
</head>
<body>
<svg width="120" height="120" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<polygon points="60,30 90,90 30,90" fill="red">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 60 70" to="360 60 70"
dur="10s" repeatCount="indefinite" />
</polygon>
</svg>
</body>
</html>
渲染单幕视频
<img style="width:550px" src="./assets/single-video.gif" />import WebVideoCreator, { VIDEO_ENCODER, logger } from "web-video-creator";
const wvc = new WebVideoCreator();
// 配置WVC
wvc.config({
// 根据您的硬件设备选择适合的编码器,这里采用的是Nvidia显卡的h264_nvenc编码器
// 编码器选择可参考 docs/video-encoder.md
mp4Encoder: VIDEO_ENCODER.NVIDIA.H264
});
// 创建单幕视频
const video = wvc.createSingleVideo({
// 需要渲染的页面地址
url: "http://localhost:8080/test.html",
// 或者可以直接设置页面内容
// content: "<h1>Hello WebVideoCreator</h1>",
// 视频宽度
width: 1280,
// 视频高度
height: 720,
// 视频帧率
fps: 30,
// 视频时长
duration: 10000,
// 视频输出路径
outputPath: "./test.mp4",
// 是否在cli显示进度条,默认是不显示
showProgress: true
});
// 监听合成完成事件
video.once("completed", result => {
logger.success(`Render Completed!!!\nvideo duration: ${Math.floor(result.duration / 1000)}s\ntakes: ${Math.floor(result.takes / 1000)}s\nRTF: ${result.rtf}`)
});
// 启动合成
video.start();
渲染多幕视频
<img style="width:550px" src="./assets/multi-video.gif" />import WebVideoCreator, { VIDEO_ENCODER, TRANSITION, logger } from "web-video-creator";
const wvc = new WebVideoCreator();
// 配置WVC
wvc.config({
// 根据您的硬件设备选择适合的编码器,这里采用的是Nvidia显卡的h264_nvenc编码器
// 编码器选择可参考 docs/video-encoder.md
mp4Encoder: VIDEO_ENCODER.NVIDIA.H264
});
// 创建多幕视频
const video = wvc.createMultiVideo({
// 视频宽度
width: 1280,
// 视频高度
height: 720,
// 视频帧率
fps: 30,
// 视频段参数
chunks: [
{
url: "http://localhost:8080/scene-1.html",
// 或者可以直接设置页面内容
// content: "<h1>Hello WebVideoCreator</h1>",
duration: 10000,
// 在第一和第二幕之间插入转场
transition: TRANSITION.CIRCLE_CROP
},
{
url: "http://localhost:8080/scene-2.html",
duration: 10000
}
],
// 视频输出路径
outputPath: "./test.mp4",
// 是否在cli显示进度条,默认是不显示
showProgress: true
});
// 监听合成完成事件
video.once("completed", result => {
logger.success(`Render Completed!!!\nvideo duration: ${Math.floor(result.duration / 1000)}s\ntakes: ${Math.floor(result.takes / 1000)}s\nRTF: ${result.rtf}`)
});
// 启动合成
video.start();
渲染分块视频合并为多幕视频
<img style="width:550px" src="./assets/chunk-video.gif" />import WebVideoCreator, { VIDEO_ENCODER, TRANSITION, logger } from "web-video-creator";
const wvc = new WebVideoCreator();
// 配置WVC
wvc.config({
// 根据您的硬件设备选择适合的编码器,这里采用的是Nvidia显卡的h264_nvenc编码器
// 编码器选择可参考 docs/video-encoder.md
mp4Encoder: VIDEO_ENCODER.NVIDIA.H264
});
// 创建分块视频1
const chunk1 = wvc.createChunkVideo({
url: "http://localhost:8080/scene-1.html",
// 或者可以直接设置页面内容
// content: "<h1>Hello WebVideoCreator</h1>",
width: 1280,
height: 720,
fps: 30,
duration: 10000,
showProgress: true
});
// 创建分块视频2
const chunk2 = wvc.createChunkVideo({
url: "http://localhost:8080/scene-2.html",
width: 1280,
height: 720,
fps: 30,
duration: 10000,
showProgress: true
});
// 等待分块们渲染完成
await Promise.all([chunk1.startAndWait(), chunk2.startAndWait()]);
// 设置chunk1和chunk2之间的转场效果为淡入淡出
chunk1.setTransition({ id: TRANSITION.FADE, duration: 500 });
// 不设置时长可以直接提供效果ID
// chunk1.setTransition(TRANSITION.FADE);
// 创建多幕视频
const video = wvc.createMultiVideo({
width: 1280,
height: 720,
fps: 30,
// 视频段
chunks: [
chunk1,
chunk2
],
// 视频输出路径
outputPath: "./test.mp4",
// 是否在cli显示进度条
showProgress: true
});
// 监听合成完成事件
video.once("completed", result => {
logger.success(`Render Completed!!!\nvideo duration: ${Math.floor(result.duration / 1000)}s\ntakes: ${Math.floor(result.takes / 1000)}s\nRTF: ${result.rtf}`)
});
// 启动合成
video.start();
全局配置
您可以全局配置WVC调整一些通用参数。
import WebVideoCreator, { VIDEO_ENCODER, AUDIO_ENCODER } from "web-video-creator";
const wvc = new WebVideoCreator();
wvc.config({
// 开启后将输出一些WVC的调试日志
debug: true,
// 指定使用的Chrome浏览器版本
browserVersion: "...",
// 建议开启,如果关闭将显示窗口并且需要启用兼容渲染模式才可正常渲染,仅用于调试画面
browserHeadless: true,
// 默认开启帧率限制,关闭它可以提高渲染效率并支持高于60fps的动画,但这会关闭GPU垂直同步可能导致画面撕裂或其它问题
browserFrameRateLimit: true,
// 开启后将输出浏览器的运行日志
browserDebug: true,
// 开启后将输出每一条执行的FFmpeg命令
ffmpegDebug: true,
// ffmpeg可执行文件路径,设置后将禁用内部的ffmpeg-static,建议您默认使用内部的FFmpeg以确保功能完整性
ffmpegExecutablePath: "...",
// ffprobe可执行文件路径,设置后将禁用内部的ffprobe-static,建议您默认使用内部的ffprobe以确保功能完整性
ffprobeExecutablePath: "...",
// 浏览器GPU加速开关,建议开启提高渲染性能,如果您没有GPU设备或遭遇了诡异的渲染问题则可以关闭它
browserUseGPU: true,
// 浏览器是否使用Angle作为渲染后端,建议开启增强渲染跨平台兼容性和性能
browserUseAngle: true,
// 是否禁用浏览器使用共享内存,当/dev/shm分区较小时建议开启此选项
browserDisableDevShm: false,
// 浏览器可执行文件路径,设置后将禁用内部的浏览器,建议您默认使用内部的浏览器以确保功能完整性
browserExecutablePath: "...",
// 浏览器启动超时时间(毫秒),设置等待浏览器启动超时时间
browserLaunchTimeout: 30000,
// 浏览器协议通信超时时间(毫秒),设置CDP协议通信超时时间
browserProtocolTimeout: 180000,
// 是否允许不安全的上下文,默认禁用,开启后能够导航到不安全的URL,但由于不安全上下文限制,将无法在页面中使用动态图像和内嵌视频
allowUnsafeContext: false,
// 兼容渲染模式,MacOS中需要启用,其它环境不建议启用,启用后将禁用HeadlessExperimental.beginFrame API调用改为普通的Page.screenshot
// 这会导致渲染效率下降40%,当你遭遇 TargetCloseError: Protocol error (HeadlessExperimental.beginFrame): Target closed 错误的时候可以尝试开启它
compatibleRenderingMode: false,
// 资源池最小浏览器实例数量
numBrowserMin: 1,
// 资源池最大浏览器实例数量
numBrowserMax: 5,
// 每个浏览器实例最小页面实例数量
numPageMin: 1,
// 每个浏览器实例最大页面实例数量
numPageMax: 5,
// 访问页面时的用户UA
userAgent: null,
// 捕获帧图质量(0-100),仅jpeg有效
frameQual

