# WebVideoCreator **Repository Path**: xzn_project/web-video-creator ## Basic Information - **Project Name**: WebVideoCreator - **Description**: 一个将Web动画渲染为视频的框架,基于Node.js+Puppeteer+Chrome+FFmpeg 实现,使用最先进的浏览器API。 - **Primary Language**: NodeJS - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 36 - **Created**: 2023-11-07 - **Last Updated**: 2023-11-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [简体中文](./README.md) | [English](./README.en-US.md)

# 简介 WebVideoCreator(简称WVC)是一个将Web动画渲染为视频的框架,基于 Node.js + Puppeteer + Chrome + FFmpeg 实现,它执行确定性的渲染,准确的以目标帧率捕获任何可在HTML5播放动画(CSS3动画/SVG动画/Lottie动画/GIF动画/APNG动画/WEBP动画)以及任何基于时间轴使用[RAF](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame)驱动的动画([anime.js](https://animejs.com/)是一个不错的选择 :D),当然您也可以调皮的使用setInterval或者setTimeout来控制动画,支持嵌入mp4和透明webm视频,还支持转场合成、音频合成与字体加载等功能。让我们[快速开始](#快速开始)。 WVC为您酷炫的动画页面创造了一个虚拟时间环境(也许可以想象成是一个《楚门的世界》),它的主要职责是将一个 [不确定性渲染的环境](./docs/renderer-env.md#不确定性的渲染环境) 转化到 [确定性渲染的环境](./docs/renderer-env.md#确定性的渲染环境)。 这一切的前提由Chrome提供的[确定性渲染模式](https://goo.gle/chrome-headless-rendering)和无头实验API支持:[HeadlessExperimental.beginFrame](https://chromedevtools.github.io/devtools-protocol/tot/HeadlessExperimental/#method-beginFrame) 答疑交流QQ群:752693580
# 特性 - 基于Node.js开发,使用非常简单,易于扩展和开发。 - 视频处理速度非常快,最快5分钟视频可在1分钟内完成渲染。 - 支持单幕和多幕视频渲染合成,多幕视频可应用[转场效果](#插入转场效果)。 - 支持分块视频合成,可以将分块分发到多个设备上渲染回传再合成为多幕视频,大幅降低长视频渲染耗时。 - 支持并行多个视频渲染合成任务,充分利用系统资源。 - API支持进行[分布式渲染](#分布式渲染方案)封装,只需对WVC进行一些封装即可将大量视频分块分发到多个设备渲染并最终取回合并输出 - 支持使用GPU加速渲染和合成,可以显著的降低视频渲染耗时。 - 支持在Windows和Linux平台部署运行。
# 视频DEMO 我们还缺少动画设计师,不过还是从开放的平台中使用WVC捕获渲染了一些优秀的动画Demo。 在这里查看所有DEMO:**[渲染示例页面](https://github.com/Vinlic/WebVideoCreator/wiki/Rendering-Example)**
# 支持的动画库 理论上所有的Web动画/图形库都能够在WVC环境正常运行,以下仅列出我已验证可用的库: [Anime.js](https://animejs.com/) / [GSAP](https://greensock.com/) / [D3.js](https://d3js.org/) / [Three.js](https://threejs.org/) / [Echart](https://echarts.apache.org/) / [Lottie-Web](http://airbnb.io/lottie/#/web) / [PixiJS](https://pixijs.download/release/docs/index.html) / [Animate.css](https://animate.style/) / [Mo.js](https://mojs.github.io/) / [Tween.js](https://tweenjs.github.io/tween.js/) 需要注意的是,如果您手动使用[RAF](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame)驱动动画,请确保从回调中接收timestamp参数设置动画的进度到该时间点,否则可能出现帧率不同步。
# 快速开始 ## 安装 ```shell # 从NPM安装WebVideoCreator npm i web-video-creator ``` 如遇到ffmpeg-static下载失败,请先设置环境变量:`FFMPEG_BINARIES_URL=https://cdn.npmmirror.com/binaries/ffmpeg-static` ## 创建本地服务器 WVC需要从Web页面中捕获动画,您可以在本地创建一个临时的Web服务器来提供静态页面服务,方便接下来的测试,使用live-server是最简单的方式之一,如果您已经有静态页面可跳过这个步骤。 ```shell # 从NPM全局安装live-server npm i -g live-server # 启用Web服务 live-server ``` 创建一个测试页面到Web服务根路径,以下html内容展示一个自动旋转的三角形svg动画。 ```html 测试页面 ``` ## 渲染单幕视频 ```javascript 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", // 视频宽度 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(); ``` ## 渲染多幕视频 ```javascript 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", 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(); ``` ## 渲染分块视频合并为多幕视频 ```javascript 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", 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调整一些通用参数。 ```javascript import WebVideoCreator, { VIDEO_ENCODER, AUDIO_ENCODER } from "web-video-creator"; const wvc = new WebVideoCreator(); wvc.config({ // 开启后将输出一些WVC的调试日志 debug: 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: "...", // 是否允许不安全的上下文,默认禁用,开启后能够导航到不安全的URL,但由于不安全上下文限制,将无法在页面中使用动态图像和内嵌视频 allowUnsafeContext: false, // 兼容渲染模式,不建议启用,启用后将禁用HeadlessExperimental.beginFrame API调用改为普通的Page.screenshot // 这会导致渲染性能下降,且部分动画可能帧率无法同步,当你遭遇 TargetCloseError: Protocol error (HeadlessExperimental.beginFrame): Target closed 错误的时候可以尝试开启它 compatibleRenderingMode: false, // 资源池最小浏览器实例数量 numBrowserMin: 1, // 资源池最大浏览器实例数量 numBrowserMax: 5, // 每个浏览器实例最小页面实例数量 numPageMin: 1, // 每个浏览器实例最大页面实例数量 numPageMax: 5, // 访问页面时的用户UA userAgent: null, // 捕获帧图质量(0-100),仅jpeg有效 frameQuality: 80, // 帧图格式(jpeg/png),建议使用jpeg,png捕获较为耗时 frameFormat: "jpeg", // BeginFrame捕获图像超时时间 beginFrameTimeout: 5000, // MP4格式的视频编码器,默认使用libx264软编码器,建议根据您的硬件选用合适的硬编码器加速合成,编码器选择可参考 docs/video-encoder.md mp4Encoder: VIDEO_ENCODER.CPU.H264, // WEBM格式的视频编码器,默认使用libvpx软编码器,建议根据您的硬件选用合适的硬编码器加速合成 webmEncoder: VIDEO_ENCODER.CPU.VP8, // 音频编码器,建议采用默认的aac编码器 audioEncoder: AUDIO_ENCODER.AAC }); ``` ## 插入音频 只需在需要渲染的html中添加 `