{"id":21040616,"url":"https://github.com/vinlic/webvideocreator","last_synced_at":"2025-04-07T06:05:15.306Z","repository":{"id":193742475,"uuid":"689399436","full_name":"Vinlic/WebVideoCreator","owner":"Vinlic","description":"🌈 A framework for rendering web animations into videos. It's implemented based on Node.js + Puppeteer + Chrome + FFmpeg, utilizing the latest browser APIs.","archived":false,"fork":false,"pushed_at":"2024-01-05T17:15:46.000Z","size":7133,"stargazers_count":166,"open_issues_count":19,"forks_count":38,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T05:06:12.203Z","etag":null,"topics":["animation","chrome","ffmpeg","nodejs","puppeteer","video","vtuber"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Vinlic.png","metadata":{"files":{"readme":"README.en-US.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-09T17:21:42.000Z","updated_at":"2025-03-25T01:59:38.000Z","dependencies_parsed_at":"2023-09-23T09:59:22.272Z","dependency_job_id":"ef6b765c-e8ab-4f54-867f-8f2e19c92ce1","html_url":"https://github.com/Vinlic/WebVideoCreator","commit_stats":null,"previous_names":["vinlic/puppeteer-video-renderer","vinlic/puppeteer-video-creator","vinlic/webvideocreator"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vinlic%2FWebVideoCreator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vinlic%2FWebVideoCreator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vinlic%2FWebVideoCreator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vinlic%2FWebVideoCreator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Vinlic","download_url":"https://codeload.github.com/Vinlic/WebVideoCreator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601447,"owners_count":20964864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","chrome","ffmpeg","nodejs","puppeteer","video","vtuber"],"created_at":"2024-11-19T13:47:26.995Z","updated_at":"2025-04-07T06:05:15.269Z","avatar_url":"https://github.com/Vinlic.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[简体中文](./README.md) | [English](./README.en-US.md)\n\n\u003cp align=\"center\" style=\"background:#fff\"\u003e\n  \u003cimg width=\"650px\" src=\"./assets/web-video-creator.png\" /\u003e\n\u003c/p\u003e\n\n[![NPM](https://nodei.co/npm/web-video-creator.png)](https://npmjs.org/package/web-video-creator)\n\n![GitHub](https://img.shields.io/github/license/Vinlic/WebVideoCreator)\n![GitHub package.json version](https://img.shields.io/github/package-json/v/Vinlic/WebVideoCreator)\n![npm](https://img.shields.io/npm/dt/web-video-creator)\n![GitHub Repo stars](https://img.shields.io/github/stars/Vinlic/WebVideoCreator)\n\n# Introduction\n\n🌈 WebVideoCreator (abbreviated as WVC) is a framework for rendering web animations into videos. It's implemented based on Node.js + Puppeteer + Chrome + FFmpeg. It performs deterministic rendering and captures any HTML5-playable animations (CSS3 animations/SVG animations/Lottie animations/GIF animations/APNG animations/WEBP animations) and any timeline-based animations driven by [RAF](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame). You can also mischievously use `setInterval` or `setTimeout` to control animations. WVC supports embedding or exporting MP4 and transparent WebM videos, as well as features such as transition compositing, audio synthesis, and font loading. Let's get started with the [Quick Start](#quick-start) 🍻.\n\nWVC creates a virtual time environment🕒 for your cool animated pages, which can be imagined as something akin to \"The Truman Show.\" Its main responsibility is to transform an [uncertain rendering environment](./docs/renderer-env.md#不确定性的渲染环境) into a [deterministic rendering environment](./docs/renderer-env.md#确定性的渲染环境).\n\nAll of this is made possible by Chrome's provided [deterministic rendering mode](https://goo.gle/chrome-headless-rendering) and support for the headless experimental API: [HeadlessExperimental.beginFrame](https://chromedevtools.github.io/devtools-protocol/tot/HeadlessExperimental/#method-beginFrame), This is an innovative experimental function 🧪.\n\nQ\u0026A and discussion group on QQ🐧: 752693580\n\n\u003cbr\u003e\n\n# Features\n\n- Developed using Node.js, it's very easy to use, extend, and develop further.\n- Video processing is incredibly fast, rendering a video as long as 5 minutes can be completed in just 1 minute, Check [Performance Tips](#Performance-Tips) for optimal performance.\n- Supports rendering and compositing of single scenes and multi-scene videos, with the ability to apply transition effects to multi-scene videos.\n- Supports chunked video compositing, allowing chunks to be distributed to multiple devices for rendering, then combined into multi-scene videos, significantly reducing rendering time for long videos.\n- Supports parallel rendering and compositing of multiple video tasks.\n- Support embedding or exporting webm format videos that support transparent channels.\n- API support for [distributed rendering](#distributed-rendering-solution), enabling the distribution of a large number of videos to multiple devices for rendering and final merging output with minimal wrapping of WVC.\n- Supports GPU acceleration for rendering and compositing, reducing video rendering time significantly.\n- Can be deployed and run on both Windows and Linux platforms, On MacOS, it is necessary to enable [Compatible Rendering Mode](#compatible-rendering-mode).\n\n\u003cbr\u003e\n\n# What is it for?\n\nWVC achieves perfect frame-by-frame capture of any animation on a web page. It minimizes the cost of achieving a WYSIWYG (What You See Is What You Get) experience. As a rendering backend, it currently explores the following applications:\n\n**📊 Data Visualization Video Rendering**: Combine chart libraries such as ECharts to create animated charts on the web and capture them as videos using WVC. This is useful for creating dynamic ranking videos commonly seen on platforms like TikTok, especially when combined with web scraping for data collection.\n\n**👩‍🏫 Digital Human Video Rendering**: With the popularity of AI-generated characters, various digital avatars appear on screens. WVC supports the use of transparent channel videos or mask videos on web pages, enhancing visual effects by incorporating digital humans into animations.\n\n**🎨 Content Creation Video Rendering**: Design a simple frontend animation editor and previewer to meet content creation needs. Use WVC as the backend to achieve a WYSIWYG video effect.\n\n**🎮️ Game or User Operation Replay Video Rendering**: Integrate with web-based games or applications to capture replays as videos, providing users with easy sharing and secondary editing options.\n\nThere are more application scenarios waiting for your exploration, and if you have great ideas, remember to raise an issue 🙋‍♀️...\n\n## Advantages over Screen Recording Tools?\n\n**💯 Perfect Capture**: The browser's frame composer defaults to a throttling strategy to reduce resource consumption. When drawing complex graphics or under increased system load, web animations may experience frame skipping, dropping frames, or delays. Using screen recording tools makes it difficult to ensure that every frame is captured correctly. In contrast, WVC takes control of the timing, determining when to draw the next frame onto the screen.\n\n**🎞️ Parallel Rendering**: Screen recording tools typically cannot capture the animation content of multiple tab pages simultaneously. However, WVC can capture animations in parallel across multiple pages and ultimately combine these chunks into a single long video, with support for seamless transitions.\n\n**🦾 Automation-Friendly**: Screen recording tools require manual operation. With WVC, a set of web animation templates can be combined with data scrapers and scheduled tasks to automate video production.\n\n**🧩 Quick Integration**: Screen recording tools are challenging to integrate. WVC, developed as an NPM package based on Node.js, can be quickly integrated on the backend. Some developers use it to capture game replays as videos.\n\n\u003cbr\u003e\n\n# Video Demos\n\nWe're also in need of animators! If you're passionate about open source projects, feel free to join us 😆.\n\nCheck out all the demos here: **[Rendering Example Page](https://github.com/Vinlic/WebVideoCreator/wiki/Rendering-Example)** 🤗\n\n\u003cimg src=\"assets/demo.gif\"/\u003e\n\n\u003cbr\u003e\n\n# Supported Animation Libraries\n\nIn theory, all web animation/graphics libraries should work smoothly in the WVC environment. Below, I've listed only the libraries that I have verified to be compatible:\n\n[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/)\n\nPlease note that if you manually use [RAF](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame) to drive animations, ensure that you receive the `timestamp` parameter from the callback to set the animation's progress to that timestamp. Otherwise, frame rate asynchrony may occur.\n\n\u003cbr\u003e\n\n# Quick Start\n\n## Installation\n\n```shell\n# Install WebVideoCreator from NPM\nnpm i web-video-creator\n```\n\nIf you encounter issues with the download of `ffmpeg-static`, please set the environment variable: `FFMPEG_BINARIES_URL=https://cdn.npmmirror.com/binaries/ffmpeg-static`.\n\n## Create a Local Server\n\nWVC needs to capture animations from web pages, and you can create a temporary web server locally to serve static pages for testing purposes. One of the simplest ways to do this is by using `live-server`. If you already have static web pages, you can skip this step.\n\n```shell\n# Install live-server globally from NPM\nnpm i -g live-server\n# Start the web server\nlive-server\n```\n\nCreate a test page in the root directory of the web server. The following HTML content demonstrates an automatically rotating red triangle SVG animation:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"utf-8\" /\u003e\n        \u003ctitle\u003eTest Page\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003csvg width=\"120\" height=\"120\" viewBox=\"0 0 120 120\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"\n        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\u003e\n            \u003cpolygon points=\"60,30 90,90 30,90\" fill=\"red\"\u003e\n                \u003canimateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"rotate\" from=\"0 60 70\" to=\"360 60 70\"\n                    dur=\"10s\" repeatCount=\"indefinite\" /\u003e\n            \u003c/polygon\u003e\n        \u003c/svg\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Rendering Single Video\n\n\u003cimg style=\"width:550px\" src=\"./assets/single-video.gif\" /\u003e\n\n```javascript\nimport WebVideoCreator, { VIDEO_ENCODER, logger } from \"web-video-creator\";\n\nconst wvc = new WebVideoCreator();\n\n// Configure WVC\nwvc.config({\n    // Choose an appropriate encoder based on your hardware. Here, we are using the h264_nvenc encoder for Nvidia graphics cards.\n    // Encoder selection can refer to docs/video-encoder.md\n    mp4Encoder: VIDEO_ENCODER.NVIDIA.H264\n});\n\n// Create a single-scene video\nconst video = wvc.createSingleVideo({\n    // URL of the page to be rendered\n    url: \"http://localhost:8080/test.html\",\n    // or can directly set the page content:\n    // content: \"\u003ch1\u003eHello WebVideoCreator\u003c/h1\u003e\",\n    // Video width\n    width: 1280,\n    // Video height\n    height: 720,\n    // Video frame rate\n    fps: 30,\n    // Video duration\n    duration: 10000,\n    // Output path for the video\n    outputPath: \"./test.mp4\",\n    // Display progress bar in the command line\n    showProgress: true\n});\n\n// Listen for the completion event\nvideo.once(\"completed\", result =\u003e {\n    logger.success(`Render Completed!!!\\nvideo duration: ${Math.floor(result.duration / 1000)}s\\ntakes: ${Math.floor(result.takes / 1000)}s\\nRTF: ${result.rtf}`)\n});\n\n// Start rendering\nvideo.start();\n```\n\n## Rendering Multi Video\n\n\u003cimg style=\"width:550px\" src=\"./assets/multi-video.gif\" /\u003e\n\n```javascript\nimport WebVideoCreator, { VIDEO_ENCODER, TRANSITION, logger } from \"web-video-creator\";\n\nconst wvc = new WebVideoCreator();\n\n// Configure WVC\nwvc.config({\n    // Choose an appropriate encoder based on your hardware. Here, we are using the h264_nvenc encoder for Nvidia graphics cards.\n    // Encoder selection can refer to docs/video-encoder.md\n    mp4Encoder: VIDEO_ENCODER.NVIDIA.H264\n});\n\n// Create a multi-scene video\nconst video = wvc.createMultiVideo({\n    // Video width\n    width: 1280,\n    // Video height\n    height: 720,\n    // Video frame rate\n    fps: 30,\n    // Video segment parameters\n    chunks: [\n        {\n            url: \"http://localhost:8080/scene-1.html\",\n            // or can directly set the page content:\n            // content: \"\u003ch1\u003eHello WebVideoCreator\u003c/h1\u003e\",\n            duration: 10000,\n            // Insert a circular crop transition between the first and second scenes\n            transition: TRANSITION.CIRCLE_CROP\n        },\n        {\n            url: \"http://localhost:8080/scene-2.html\",\n            duration: 10000\n        }\n    ],\n    // Output path for the video\n    outputPath: \"./test.mp4\",\n    // Display progress bar in the command line\n    showProgress: true\n});\n\n// Listen for the completion event\nvideo.once(\"completed\", result =\u003e {\n    logger.success(`Render Completed!!!\\nvideo duration: ${Math.floor(result.duration / 1000)}s\\ntakes: ${Math.floor(result.takes / 1000)}s\\nRTF: ${result.rtf}`)\n});\n\n// Start rendering\nvideo.start();\n```\n\n## Rendering Chunk Video and Combining into Multi Video\n\n\u003cimg style=\"width:550px\" src=\"./assets/chunk-video.gif\" /\u003e\n\n```javascript\nimport WebVideoCreator, { VIDEO_ENCODER, TRANSITION, logger } from \"web-video-creator\";\n\nconst wvc = new WebVideoCreator();\n\n// Configure WVC\nwvc.config({\n    // Choose an appropriate encoder based on your hardware. Here, we are using the h264_nvenc encoder for Nvidia graphics cards.\n    // Encoder selection can refer to docs/video-encoder.md\n    mp4Encoder: VIDEO_ENCODER.NVIDIA.H264\n});\n\n// Create chunk video 1\nconst chunk1 = wvc.createChunkVideo({\n    url: \"http://localhost:8080/scene-1.html\",\n    // or can directly set the page content:\n    // content: \"\u003ch1\u003eHello WebVideoCreator\u003c/h1\u003e\",\n    width: 1280,\n    height: 720,\n    fps: 30,\n    duration: 10000,\n    showProgress: true\n});\n\n// Create chunk video 2\nconst chunk2 = wvc.createChunkVideo({\n    url: \"http://localhost:8080/scene-2.html\",\n    width: 1280,\n    height: 720,\n    fps: 30,\n    duration: 10000,\n    showProgress: true\n});\n\n// Wait for the chunks to finish rendering\nawait Promise.all([chunk1.startAndWait(), chunk2.startAndWait()]);\n\n// Set the transition effect between chunk1 and chunk2 to fade in and out\nchunk1.setTransition({ id: TRANSITION.FADE, duration: 500 });\n\n// Create a multi-scene video\nconst video = wvc.createMultiVideo({\n    width: 1280,\n    height: 720,\n    fps: 30,\n    // Video segments\n    chunks: [\n        chunk1,\n        chunk2\n    ],\n    // Output path for the video\n    outputPath: \"./test.mp4\",\n    // Display progress bar in the command line\n    showProgress: true\n});\n\n// Listen for the completion event\nvideo.once(\"completed\", result =\u003e {\n    logger.success(`Render Completed!!!\\nvideo duration: ${Math.floor(result.duration / 1000)}s\\ntakes: ${Math.floor(result.takes / 1000)}s\\nRTF: ${result.rtf}`)\n});\n\n// Start rendering\nvideo.start();\n```\n\n## Global Configuration\n\nYou can globally configure WVC to adjust some common parameters.\n\n```javascript\nimport WebVideoCreator, { VIDEO_ENCODER, AUDIO_ENCODER } from \"web-video-creator\";\n\nconst wvc = new WebVideoCreator();\n\nwvc.config({\n    // Enable this to output some debug logs from WVC\n    debug: true,\n    // Specify the Chrome browser version to use\n    browserVersion: \"...\",\n    // It is recommended to enable this. If disabled, the window will be displayed and requires compatibility rendering mode to render properly. It's only used for debugging visuals.\n    browserHeadless: true,\n    // Frame rate limit is enabled by default. Disabling it can improve rendering efficiency and support animations above 60fps. However, this might disable GPU vertical sync, potentially causing screen tearing or other issues.\n    browserFrameRateLimit: true,\n    // Enable this to output browser runtime logs\n    browserDebug: true,\n    // Enable this to output each executed FFmpeg command\n    ffmpegDebug: true,\n    // Path to the FFmpeg executable file; setting this will disable the internal ffmpeg-static; it's recommended to use the internal FFmpeg for completeness\n    ffmpegExecutablePath: \"...\",\n    // Path to the ffprobe executable file; setting this will disable the internal ffprobe-static; it's recommended to use the internal ffprobe for completeness\n    ffprobeExecutablePath: \"...\",\n    // Browser GPU acceleration switch; recommended to enable for improved rendering performance; if you don't have a GPU or encounter rendering issues, you can disable it\n    browserUseGPU: true,\n    // Path to the browser executable file; setting this will disable the internal browser; it's recommended to use the internal browser for completeness\n    browserExecutablePath: \"...\",\n    // Allow unsafe contexts, false by default. Once enabled, users can navigate to unsafe URLs, but due to unsafe context restrictions, dynamic images and embedded videos cannot be used on the page\n    allowUnsafeContext: false,\n    // Compatible Rendering Mode is necessary on MacOS but not recommended for other environments; enabling this will disable HeadlessExperimental.beginFrame API calls and use regular Page.screenshot, which can lead to decreased rendering performance and frame rate desynchronization in some animations; you can try enabling it if you encounter the error \"TargetCloseError: Protocol error (HeadlessExperimental.beginFrame): Target closed\"\n    compatibleRenderingMode: false,\n    // Minimum number of browser instances in the resource pool\n    numBrowserMin: 1,\n    // Maximum number of browser instances in the resource pool\n    numBrowserMax: 5,\n    // Minimum number of page instances per browser instance\n    numPageMin: 1,\n    // Maximum number of page instances per browser instance\n    numPageMax: 5,\n    // User-agent string to use when accessing pages\n    userAgent: null,\n    // Frame capture quality (0-100); only effective for jpeg\n    frameQuality: 80,\n    // Frame image format (jpeg/png); it's recommended to use jpeg as png capture is more time-consuming\n    frameFormat: \"jpeg\",\n    // Timeout for capturing images with BeginFrame\n    beginFrameTimeout: 5000,\n    // Video encoder for MP4 format; by default, it uses the libx264 software encoder; it's recommended to choose the appropriate hardware encoder for acceleration based on your hardware, Encoder selection can refer to docs/video-encoder.md.\n    mp4Encoder: VIDEO_ENCODER.CPU.H264,\n    // Video encoder for WEBM format; by default, it uses the libvpx software encoder; it's recommended to choose the appropriate hardware encoder for acceleration based on your hardware\n    webmEncoder: VIDEO_ENCODER.CPU.VP8,\n    // Audio encoder; it's recommended to use the default AAC encoder\n    audioEncoder: AUDIO_ENCODER.AAC\n});\n```\n\n## Inserting Audio\n\nTo add audio to your rendered HTML, simply include an `\u003caudio\u003e` element with the desired audio file. You can also set attributes like `loop`, and WVC will automatically include the audio track for looping in the video.\n\n```html\n\u003caudio src=\"bgm.mp3\" loop\u003e\u003c/audio\u003e\n```\n\nYou can also set various attributes to control the audio's behavior. These attributes do not always need to be paired, so you can customize them according to your needs.\n\n```html\n\u003c!-- Control the audio volume to half the original level --\u003e\n\u003caudio src=\"bgm.mp3\" volume=\"0.5\"\u003e\u003c/audio\u003e\n\u003c!-- Start playing the audio after 3 seconds and stop it at 10 seconds --\u003e\n\u003caudio src=\"bgm.mp3\" startTime=\"3000\" endTime=\"10000\"\u003e\u003c/audio\u003e\n\u003c!-- Loop a segment of the audio from the 5th second to the 15th second --\u003e\n\u003caudio src=\"bgm.mp3\" seekStart=\"5000\" seekEnd=\"15000\" loop\u003e\u003c/audio\u003e\n\u003c!-- Apply a 300ms fade-in and 500ms fade-out to the audio --\u003e\n\u003caudio src=\"bgm.mp3\" fadeInDuration=\"300\" fadeOutDuration=\"500\"\u003e\u003c/audio\u003e\n```\n\nYou can also dynamically add and remove `\u003caudio\u003e` elements in your code to control audio entering and exiting the scene. WVC will detect them.\n\n```javascript\nconst audio = document.createElement(\"audio\");\naudio.src = \"bgm.mp3\";\n// Audio enters the scene at 3 seconds\nsetTimeout(() =\u003e document.body.appendChild(audio), 3000);\n// Audio exits the scene at 8 seconds\nsetTimeout(() =\u003e audio.remove(), 8000);\n```\n\nOr call [captureCtx.addAudio](./docs/capture-ctx.md#capturecontextaddaudiooptions-object) on the page to add audio to the video.\n\n```javascript\n// Add a single audio track\ncaptureCtx.addAudio({\n    url: \"bgm.mp3\",\n    startTime: 500,\n    loop: true,\n    // 80% volume\n    volume: 80\n});\n// Add multiple audio tracks\ncaptureCtx.addAudios([...]);\n```\n\nYou can also directly use [addAudio](./docs/api-reference-high-level.md#singlevideoaddaudiooptions-object) in WVC to add local or remote audio to the video.\n\n```javascript\nconst video = wvc.createSingleVideo({ ... });\n// Add a single audio track\nvideo.addAudio({\n    // url: \"http://.../bgm.mp3\"\n    path: \"bgm.mp3\",\n    startTime: 500,\n    loop: true,\n    // 80% volume\n    volume: 80\n});\n// Add multiple audio tracks\nvideo.addAudios([...]);\n```\n\nThis operation also applies to MultiVideo and ChunkVideo.\n\n## Inserting Video\n\nCurrently, WVC supports `mp4` and `webm` video formats. To insert a video into your rendered HTML, include a `\u003cvideo\u003e` element with the desired video file. You can set attributes like `loop` and `muted`. If your src does not contain the `. mp4` suffix name, it may not be recognized. Please add the `capture` attribute to identify the element that needs to be captured.\n\n```html\n\u003cvideo src=\"background.mp4\" loop muted\u003e\u003c/video\n```\n\nIf you wish to insert a video with a transparent channel, see: [Transparent Channel Videos](#transparent-channel-videos). If you are interested in video frame rate synchronization or transparent video rendering, you can refer to: [Technical Implementation](#technical-implementation).\n\nSimilar to audio, you can set various attributes to control the video's behavior, and these attributes do not always need to be paired.\n\n```html\n\u003c!-- Control the audio volume to 70% of the original --\u003e\n\u003cvideo src=\"test.mp4\" volume=\"0.7\"\u003e\u003c/video\u003e\n\u003c!-- Start playing the video after 3 seconds and stop it at 10 seconds --\u003e\n\u003cvideo src=\"test.mp4\" startTime=\"3000\" endTime=\"10000\"\u003e\u003c/video\u003e\n\u003c!-- Loop a segment of the video from the 5th second to the 15th second --\u003e\n\u003cvideo src=\"test.mp4\" seekStart=\"5000\" seekEnd=\"15000\" loop\u003e\u003c/video\u003e\n\u003c!-- Apply a 300ms fade-in and 500ms fade-out to the video --\u003e\n\u003cvideo src=\"test.mp4\" fadeInDuration=\"300\" fadeOutDuration=\"500\"\u003e\u003c/video\u003e\n```\n\nYou can dynamically add and remove `\u003cvideo\u003e` elements in your code to control video entering and exiting the scene. WVC will detect them.\n\n```javascript\nconst video = document.createElement(\"video\");\nvideo.src = \"test.mp4\";\n// Video enters the scene at 3 seconds\nsetTimeout(() =\u003e document.body.appendChild(video), 3000);\n// Video exits the scene at 8 seconds\nsetTimeout(() =\u003e video.remove(), 8000);\n```\n\nIf you are using some front-end frameworks to implement animation content, WVC may not be able to listen to your changes to the `\u003cvideo\u003e` element (such as hiding or displaying). Please replace the element with the `\u003ccanvas video-capture\u003e` element and prompt WVC to notice that it is a video canvas through `video-capture` attribute.\n\n```html\n\u003ccanvas src=\"test.mp4\" video-capture\u003e\u003c/canvas\u003e\n```\n\n### Transparent Channel Videos\n\nTransparent videos are great for compositing digital avatars (e.g., VTubers) into video scenes. Please refer to **[Rendering Example Page](https://github.com/Vinlic/WebVideoCreator/wiki/Rendering-Example)** Last Demo\n\nIn WVC, transparent videos should be in the `webm` format. Internally, they will be re-encoded into two mp4 container videos: one for the color base video and one for the mask video. These videos will be used for blending and drawing using the `globalCompositeOperation` in the browser canvas.\n\nFor users, it's seamless. You just need to include a `\u003cvideo\u003e` element in your HTML with the `src` set to the webm video file.\n\n```html\n\u003cvideo src=\"vtuber.webm\"\u003e\u003c/video\u003e\n```\n\nWebm encoding and decoding can be time-consuming. If you can obtain the original mp4 video and the mask mp4 video, it's a better solution. Just add the `maskSrc` attribute.\n\n```html\n\u003cvideo src=\"vtuber.mp4\" maskSrc=\"vtuber_mask.mp4\"\u003e\u003c/video\u003e\n```\n\n## Inserting Animated Images\n\nAnimated images refer to sequence frame animations in `gif` / `apng` / `webp` formats. They can naturally play in the browser, but their frame rate is usually uncontrollable. WVC proxies their rendering, replacing `img` elements with `canvas` elements, and uses ImageDecoder to decode and draw each frame in sync with virtual time.\n\nThe following animated images can be rendered as well, and you can style them as usual.\n\n```html\n\u003cimg src=\"test.gif\"/\u003e\n\u003cimg src=\"test.apng\"/\u003e\n\u003cimg src=\"test.webp\"/\u003e\n```\n\nIf you are using some front-end frameworks to implement animation content, WVC may not be able to listen to your changes to the `\u003cimg\u003e` element (such as hiding or displaying). Please replace the element with the `\u003ccanvas dyimage-capture\u003e` element and prompt WVC to notice that it is a dyanmic image canvas through `dyimage-capture` attribute.\n\n```html\n\u003ccanvas src=\"test.gif\" dyimage-capture\u003e\u003c/canvas\u003e\n```\n\n## Inserting Lottie Animations\n\nWVC comes with the built-in [lottie-web](http://airbnb.io/lottie/#/web) animation library. If you have your own Lottie animations in your web page, they should work seamlessly with WVC.\n\nSimply insert a `\u003clottie\u003e` element and set the `src` attribute.\n\n```html\n\u003clottie src=\"example.json\"\u003e\u003c/lottie\u003e\n```\n\nIf you are using some front-end frameworks to implement animation content, WVC may not be able to listen to your changes to the `\u003clottie\u003e` element (such as hiding or displaying). Please replace the element with the `\u003ccanvas lottie-capture\u003e` element and prompt WVC to notice that it is a lottie canvas through `lottie-capture` attribute.\n\n```html\n\u003ccanvas src=\"example.json\" lottie-capture\u003e\u003c/canvas\u003e\n```\n\n## Applying Fonts\n\nWVC can detect `@font-face` declarations in stylesheets and wait for the fonts to load before starting rendering.\n\n```html\n\u003cstyle\u003e\n    @font-face {\n        font-family: \"FontTest\";\n        src: url(\"font.ttf\") format(\"truetype\");\n    }\n\u003c/style\u003e\n\u003cp style='font-family: \"FontTest\"'\u003eHello World\u003c/p\u003e\n```\n\nAlternatively, you can register local or remote fonts through code.\n\n```javascript\nconst video = wvc.createSingleVideo({ ... });\n// Register a single font\nvideo.registerFont({\n    // url: \"http://.../font.ttf\"\n    path: \"font.ttf\",\n    family: \"FontTest\",\n    format: \"truetype\"\n});\n// Register multiple fonts\nvideo.registerFonts([...]);\n```\n\nMake sure the fonts can be loaded; otherwise, rendering may not start.\n\n## Inserting Transition Effects\n\nWVC supports the use of [Xfade](https://trac.ffmpeg.org/wiki/Xfade) filters supported by FFmpeg to create transition effects. You can refer to the [list of transitions](./docs/transition.md).\n\nEach chunk video parameter can be configured with a transition effect and its duration.\n\n```javascript\nimport WebVideoCreator, { TRANSITION } from \"web-video-creator\";\n\n...\n\nconst video = wvc.createMultiVideo({\n    ...\n    // Video segment parameters\n    chunks: [\n        {\n            url: \"http://localhost:8080/scene-1.html\",\n            duration: 10000,\n            // Insert a fade in/out transition between the first and second scenes\n            transition: {\n                id: TRANSITION.FADE,\n                duration: 500\n            },\n            // If you don't need to set the duration, you can directly set the transition ID\n            // transition: TRANSITION.FADE\n        },\n        {\n            url: \"http://localhost:8080/scene-2.html\",\n            duration: 10000\n        }\n    ],\n    ...\n});\n\n...\n```\n\nIt's important to note that applying transitions will result in a shorter total video duration since the transition effect effectively overlaps a portion of two video segments. For example, if you insert a fade transition between two 5-second segments, the resulting video will have a duration of 9 seconds.\n\nLottie animations are also suitable for use as transition effects. You can play a full-screen Lottie animation for half of the duration at the end of one video segment and then play another full-screen Lottie animation for the remaining half at the beginning of the next video segment to create more dynamic transition effects.\n\n## Export videos with transparent channels\n\nWVC supports you to set the background opacity `backgroundOpacity` option to achieve transparent or semi transparent background video output, with a value range of **0-1**, Please ensure that the output video path suffix name or format option is **webm**.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set a completely transparent background\n    backgroundOpacity: 0\n});\n```\n\n## Delayed Rendering Start\n\nBy default, WVC starts rendering immediately after the page navigation is complete. If you\n\n want to perform some tasks before rendering, you can disable automatic rendering start in the options. In this case, remember to call [captureCtx.start()](./docs/capture-ctx.md#capturecontextstart) in your page code, or rendering will be blocked indefinitely.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    url: \"http://localhost:8080/test.html\",\n    width: 1280,\n    height: 720,\n    duration: 10000,\n    // Disable automatic rendering start\n    autostartRender: false\n});\n```\n\nIn your page code, call the start function when appropriate.\n\n```html\n\u003cscript\u003e\n    // 数据加载完成后启动渲染\n    loadData()\n        .then(() =\u003e captureCtx.start())\n        .catch(err =\u003e console.error(err));\n\u003c/script\u003e\n```\n\n\u003cbr\u003e\n\n## Start Capturing at a Specified Time Point\n\nBy default, WVC begins capturing the screen from the 0 time point after rendering starts. However, it also supports initiating screen capture from other time points.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    url: \"http://localhost:8080/test.html\",\n    width: 1280,\n    height: 720,\n    // Start capturing from the 5-second mark\n    startTime: 5000,\n    duration: 10000\n});\n```\n\n\u003cbr\u003e\n\n## Pre-render Page Operations\n\n```javascript\nconst video = wvc.createSingleVideo({\n    url: \"http://localhost:8080/test.html\",\n    width: 1280,\n    height: 720,\n    duration: 10000,\n    pagePrepareFn: async page =\u003e {\n        // Get the puppeteer Page object\n        const _page = page.target;\n        // Click the button\n        await _page.tap(\"#play-button\");\n    }\n});\n```\n\n## Using Action Sequences\n\nWVC allows you to set actions to be executed at specific time points within a video. This feature enables convenient manipulation of a page at arbitrary intervals within a video. The following code is used to perform scrolling at the 3rd, 6th, and 9th seconds of the video.\n\n```javascript\nconst actionFn = async (page) =\u003e {\n    const _page = page.target;\n    await _page.evaluate(() =\u003e {\n        window.scrollTo({\n            top: window.scrollY + 1280,\n            behavior: \"smooth\"\n        });\n    });\n};\nconst video = wvc.createSingleVideo({\n    width: 1080,\n    height: 1280,\n    fps: 60,\n    outputPath: \"./t2.mp4\",\n    showProgress: true,\n    url: \"https://www.bilibili.com/v/popular/all/\",\n    // Setting up the action sequence\n    timeActions: {\n        3000: actionFn,\n        6000: actionFn,\n        9000: actionFn\n    },\n    duration: 10000\n});\n```\n\n## Page Console Output\n\nIf you want to see the page's logs, you can enable `consoleLog` in the video options. If there are embedded videos, you can also enable `videoPreprocessLog` to output video preprocessing logs.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Output logs from the page's console\n    consoleLog: true,\n    // Output video preprocessing logs for embedded videos\n    videoPreprocessLog: true\n});\n```\n\n## Capture a Cover Image\n\nAfter rendering a video, you can capture a frame image and save it, which can be used as the video's cover image.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Enable cover image capture\n    coverCapture: true,\n    // Time in milliseconds to capture the image (default is 20% of the video's duration)\n    coverCaptureTime: 1000,\n    // Image format for capture (jpg/png/bmp), default is jpg\n    coverCaptureFormat: \"jpg\"\n});\n```\n\n## Insert a Cover Image\n\nWVC supports inserting an image into the first frame of the video, which will be displayed when the video is not playing.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set the path to the additional cover image, supports jpg/png/bmp\n    attachCoverPath: \"./cover.jpg\"\n});\n```\n\n## Adjust Video Volume\n\nYou can control the overall volume of the output video.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set the video volume to 80% of the original\n    volume: 80\n});\n```\n\n## Control Output Video Quality\n\nWVC allows you to control video image quality using `videoQuality` or `videoBitrate`.\n\n`videoQuality` is used to calculate the bitrate based on the total pixel count of the image. The following is the method used by WVC to calculate the video bitrate internally:\n\n```javascript\nconst pixels = width * height;\nconst videoBitrate = (2560 / 921600 * pixels) * (videoQuality / 100);\n```\n\nYou can provide `videoQuality` (0-100) in the video options:\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set video quality to 80%\n    videoQuality: 80\n});\n```\n\nIf you find the bitrate inappropriate, you can set `videoBitrate` separately:\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set video bitrate to 8Mbps\n    videoBitrate: \"8192k\"\n});\n```\n\nAdditionally, you can adjust the frame image quality when using jpeg as the frame format by setting `frameQuality`. For details, see [Global Configuration](#global-configuration).\n\nYou can also adjust audio quality by setting the audio bitrate `audioBitrate`:\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set audio bitrate to 320Kbps\n    audioBitrate: \"320k\"\n});\n```\n\n## Change Pixel Format\n\nWVC currently supports output in `yuv420p`, `yuv444p`, and `rgb24` pixel formats. It defaults to using the more compatible `yuv420p`. If you notice significant color differences between the output video and the original page, you can switch to `rgb24` to improve the issue.\n\n```javascript\nconst video = wvc.createSingleVideo({\n    ...,\n    // Set the pixel format to rgb24\n    pixelFormat: \"rgb24\"\n});\n```\n\n\u003cbr\u003e\n\n# Video Encoder Selection\n\nWhen rendering frames from the browser and feeding them into FFmpeg, it's necessary to encode the image data at the specified frame rate and store it in a specified format container using a video encoder. Video encoding is a resource-intensive operation, and choosing a hardware encoder can accelerate this process and reduce CPU load.\n\nPlease refer to the [Video Encoder Guide](./docs/video-encoder.md) for a list of supported video encoders by WVC.\n\n\u003cbr\u003e\n\n# Progress Monitoring\n\nYou can use the `progress` event of the video instance to monitor the rendering and synthesis progress.\n\n```javascript\nconst video = wvc.createSingleVideo({ ... });\nvideo.on(\"progress\", (progress, synthesizedFrameCount, totalFrameCount) =\u003e {\n    // Output progress / synthesized frame count / total frame count\n    console.log(progress, synthesizedFrameCount, totalFrameCount);\n});\n```\n\nThis also applies to `MultiVideo` / `ChunkVideo` and the synthesisers in the low-level API.\n\n\u003cbr\u003e\n\n# Exception Handling\n\n## Throwing Errors\n\nYou can actively throw errors in the page to interrupt rendering.\n\n```html\n\u003cscript\u003e\n    captureCtx.throwError(-1, \"Abort\");\n\u003c/script\u003e\n```\n\n## Listening for Page Crashes\n\nIf your page involves heavy computations or consumes excessive memory, it may crash, causing rendering to be interrupted.\n\nIf you're using the high-level API, you can be notified of page crashes through the `pageCrashed` event of the video instance.\n\n```javascript\nconst video = wvc.createSingleVideo({ ... });\n// Output crash errors when an error occurs\nvideo.on(\"pageCrashed\", err =\u003e console.error(err));\n```\n\nWhen using the low-level API, you can listen for page crashes through the `crashed` event of the Page instance.\n\n```javascript\n// Output crash errors when an error occurs\npage.on(\"crashed\", err =\u003e console.error(err));\n```\n\n## Listening for Other Errors\n\nIf you're using the high-level API, you can listen for errors through the `error` event of the video instance.\n\n```javascript\nconst video = wvc.createSingleVideo({ ... });\nvideo.on(\"error\", err =\u003e console.error(err));\n```\n\nWhen using the low-level API, you can listen for errors through the `error` event of the Page instance.\n\n```javascript\npage.on(\"error\", err =\u003e console.error(err));\n```\n\n## Compatible Rendering Mode\n\nOn MacOS, due to Chrome's lack of support for the BeginFrame API, it is necessary to switch to the compatible rendering mode for proper functionality. This mode may result in a decrease in rendering efficiency of around 40%. It is recommended to deploy on Windows or Linux devices for better performance.\n\n```javascript\n// Enable compatible rendering mode\nwvc.config({ compatibleRenderingMode: true });\n```\n\n\u003cbr\u003e\n\n# Cache Management\n\nTo optimize task launching and rendering time, WVC generally maintains four types of caches: `Browser Cache`, `Preprocess Cache`, `Synthesize Cache`, and `Local Font Cache`.\n\n**Browser Cache**: Contains cached files and records generated by the page, reducing page loading time.\n\n**Preprocess Cache**: When rendering content references remote resources, the preprocessor attempts to fetch and cache them locally, reducing bandwidth consumption.\n\n**Synthesize Cache**: When combining multiple video chunks into a whole, pre-rendered chunks serve as the synthesize cache. Typically, WVC clears this cache after synthesis is complete.\n\n**Local Font Cache**: When using `registerFonts` to register local fonts for successful injection into the page, a copy of fonts from the source path is stored in the cache.\n\n## Clearing Cache\n\n```javascript\n// Clear browser cache\nwvc.cleanBrowserCache();\n// Clear preprocess cache\nwvc.cleanPreprocessCache();\n// Clear synthesize cache\nwvc.cleanSynthesizeCache();\n// Clear local font cache\nwvc.cleanLocalFontCache();\n```\n\n\u003cbr\u003e\n\n# API Reference\n\n## High-Level API\n\nIn most cases, it is recommended to use the high-level API because it is simple but may be less flexible.\n\n[API Reference High Level](./docs/api-reference-high-level.md)\n\n## Low-Level API\n\n[API Reference Low Level](./docs/api-reference-low-level.md)\n\n\u003cbr\u003e\n\n# Distributed Rendering\n\nIf you have multiple devices available for rendering, you can deploy WVC on these devices. WVC provides `MultiVideo` and `ChunkVideo`, allowing you to divide the animation pages into many segments (e.g., 0-10 seconds, 10-20 seconds, etc.). Distribute their parameters to different WVC instances on different devices, create ChunkVideo instances on these devices, and execute parallel rendering to generate multiple video segments (`ts`). These segments are then sent back to the core node, where they are combined, and transitions, audio tracks, and output are handled. **The distribution and return process is not yet implemented in WVC, but it is not difficult, and you can wrap it according to your own scenario. Contributions to WVC are welcome through [PR](https://github.com/Vinlic/WebVideoCreator/pulls)!**\n\n\u003cbr\u003e\n\n# Performance Tips\n\nPerformance is typically influenced by the complexity of animations and media. To improve performance:\n\n- Divide long animations into multiple segments. For instance, you can include a seek parameter with each page URL, load the page, and seek to a specified time to start playing. Then, render and combine them as a multi-video to significantly reduce rendering time for long videos.\n\n- Render more video chunks in parallel. To maximize system resources, select the number of parallel chunks based on the number of CPU threads, assuming your system has sufficient memory.\n\n- CPU clock speed has a significant impact on baseline performance. Consumer-grade CPUs often have high clock speeds, which can lead to better performance.\n\n- Consider using GPU acceleration for rendering and compositing. If your device has a GPU but it's not being utilized, check the configuration settings or report the issue.\n\n- Using an SSD (Solid State Drive) can improve hard disk cache write performance during parallel rendering, reducing rendering time.\n\n- Select the right video hardware encoder. By default, software encoders are used (libx264 for mp4 and libvpx for webm). If you have integrated or discrete graphics, configure the hardware encoders they support.\n\n- Some time may be spent on network file transfers. It's advisable to deploy static file services on the same server or access the file server from a local network.\n\n- Reducing the output video resolution and frame rate is the most effective way to reduce time consumption.\n\nHere are the performance parameters for my personal computer as a reference:\n\nOperating System: Windows 10 (Better performance on Linux)\n\nCPU: AMD Ryzen 7 3700X (Clock speed 3.6-4.4GHz, 8 cores, 16 threads)\n\nGPU: Nvidia GeForce GTX 1660 SUPER (6GB VRAM, NVENC support)\n\nRAM: 16GB (DDR4 2400MHz)\n\nVideo Type: SVG animations + GIFs + Lottie animations\n\nVideo Resolution: 1280x720\n\nVideo Frame Rate: 30\n\nVideo Duration: 300s (5 minutes)\n\nRendering Time: 61s (1 minute)\n\nReal-Time Rate: 4.844\n\nParallel Rendering Count: 16\n\n\u003cbr\u003e\n\n# Limitations\n\n- Constrained by browser [secure context restrictions](https://w3c.github.io/webappsec-secure-contexts/), WebVideoCreator can only access `localhost` / `127.0.0.1` or domains using HTTPS with valid certificates. For security reasons, it's recommended to use a local static server (e.g., `live-server` is a good choice), You can also use the content option to directly set the page content to avoid URL restrictions.\n\n- The headless experimental API on Mac systems may cause crashes and needs to be switched to compatibility rendering mode to run. However, compatibility rendering mode has various issues, so it is not recommended for Mac systems. See [Compatibility Rendering Mode](#compatible-rendering-mode).\n\n- WebVideoCreator is a pure ESM package and cannot be imported using CommonJS-style `require`. If you still want to use `require` to import it, refer to this [gist](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) for guidance.\n\n- The page jump request during the video rendering process will be intercepted because jumping to the page will result in the loss of capture context.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinlic%2Fwebvideocreator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvinlic%2Fwebvideocreator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinlic%2Fwebvideocreator/lists"}