ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hyperframes实战:用HTML+AI批量生成MP4视频

Hyperframes实战:用HTML+AI批量生成MP4视频 1. 从 hyperframes 说起一个被低估的 HTML 转视频思路第一次看到 hyperframes 这个词是在一个做自动化内容生产的小圈子里。当时有人丢出来一个需求手里有一堆用 HTML 写好的页面模板想批量变成 MP4 视频问有没有靠谱的方案。底下有人回了一句“hyperframes 了解一下”然后就没下文了。我自己去翻了一圈发现这个概念其实并不复杂但真正把它用起来、用顺手的人并不多。hyperframes 本质上是一种把 HTML 页面当作视频帧来处理的思路。你可以把它理解成浏览器渲染出来的每一个画面就是一帧视频。传统做视频要么用剪辑软件手动拖时间轴要么用 After Effects 做模板要么用 FFmpeg 命令行拼图片。而 hyperframes 走的是另一条路——用 HTML CSS JS 描述画面然后通过工具把这个画面按时间轴逐帧截取最后合成 MP4。这条路的好处非常明显你不需要学剪辑软件只要会写网页就能做视频。为什么这个思路现在越来越火因为 AI coding agents 的普及改变了很多事情。以前写一个 HTML 页面要手敲现在你可以让 AI 帮你生成一个带canvas动画的页面或者一个用 CSS keyframes 做的动态图表。生成完之后hyperframes 负责把它变成视频。整个链路里人只需要描述需求剩下的交给工具。这也是为什么 hyperframes 会和 CLI、AI coding agents、MP4 这些词绑在一起出现在热搜里。这篇文章适合谁看如果你是一个前端开发者想把手里的 HTML 页面变成可分享的视频如果你是一个做自动化内容的人想批量生产短视频素材如果你是一个刚接触 AI coding agents 的人想知道怎么把 AI 生成的网页变成实际可用的视频文件——那这篇内容就是写给你的。我会从整体设计思路讲到具体实操包括参数怎么算、坑在哪里、怎么排查问题尽量让你看完就能动手。2. 整体设计与思路拆解为什么用 HTML 做视频帧2.1 核心逻辑浏览器就是渲染引擎传统视频制作的核心是“帧”。一秒钟 24 帧、30 帧或者 60 帧每一帧是一张图片。剪辑软件做的事情就是把这些图片按顺序排列加上音频导出成视频文件。hyperframes 的思路没有偏离这个本质它只是换了一种生成帧的方式——不是用相机拍也不是用设计软件画而是用浏览器渲染。浏览器本身就是一个非常强大的渲染引擎。它支持 HTML 结构、CSS 样式、JS 动画、Canvas 绘图、SVG 矢量图、WebGL 3D 渲染。你平时看到的网页动效本质上就是浏览器在按时间刷新画面。如果把浏览器的刷新过程按固定间隔截取下来每一张截图就是一帧。把这些帧拼起来就是视频。这个逻辑听起来简单但真正落地的时候有几个关键问题要解决。第一怎么保证截取的帧率稳定第二怎么控制动画的时间轴第三怎么把截取的帧合成 MP4这三个问题分别对应了 hyperframes 方案里的三个核心环节渲染控制、时间轴管理、视频编码。2.2 方案选型为什么不用录屏而用逐帧截取很多人第一反应是既然浏览器能播放动画那我直接录屏不就行了录屏确实简单OBS 一开播放页面录制结束。但录屏有几个硬伤。第一个硬伤是帧率不稳定。录屏软件受限于系统性能掉帧是常态。你录一个 60fps 的动画实际出来可能只有 45fps画面会卡顿。而逐帧截取可以精确控制每一帧的生成时间不受系统实时性能影响。第二个硬伤是分辨率不可控。录屏出来的分辨率取决于窗口大小想输出 4K 就得有 4K 显示器。逐帧截取可以直接设置 viewport 尺寸想输出 3840x2160 就设这个尺寸跟显示器无关。第三个硬伤是自动化困难。录屏需要人工操作批量生产几乎不可能。逐帧截取可以写成脚本输入一批 HTML 文件输出一批 MP4全程无人值守。所以 hyperframes 方案的核心选择是用无头浏览器逐帧截取而不是录屏。无头浏览器headless browser是没有界面的浏览器可以在命令行里运行非常适合自动化。常见的无头浏览器方案有 Puppeteer、Playwright、以及一些基于 Chromium 的封装工具。它们都提供了截图接口可以精确控制截取时机。2.3 时间轴管理用代码控制每一帧的内容逐帧截取解决了“怎么拿帧”的问题但还有一个更关键的问题每一帧的内容怎么控制如果只是截取一个静态页面那所有帧都一样视频就是一张静止图片。要让画面动起来必须让页面内容随时间变化。这里有几种常见的做法。第一种是用 CSS 动画通过animation-delay和animation-duration控制元素在特定时间点的状态。第二种是用 JS 的requestAnimationFrame在每一帧回调里更新 DOM 或 Canvas。第三种是用专门的动画库比如 GSAP、Anime.js它们提供了更精确的时间轴控制。在 hyperframes 的实践里最推荐的是第二种和第三种结合。因为逐帧截取的时候你需要精确知道“当前是第几帧”然后让页面渲染出这一帧对应的画面。如果依赖 CSS 动画的自动播放截取时机很难对齐。更好的做法是把动画时间轴暴露成一个全局变量截取脚本在每一帧之前设置这个变量然后触发页面重绘再截图。举个例子假设你要做一个 5 秒、30fps 的视频总共 150 帧。截取脚本会循环 150 次每次设置window.currentFrame i页面里的 JS 监听这个变量根据帧号计算所有元素的位置、透明度、旋转角度然后更新 DOM。更新完成后脚本调用截图接口拿到这一帧的图片。这样每一帧都是精确可控的。2.4 视频编码从帧序列到 MP4拿到 150 张 PNG 图片之后最后一步是合成 MP4。这一步通常用 FFmpeg 完成。FFmpeg 是一个命令行视频处理工具功能极其强大。把图片序列转成视频的基本命令是这样的ffmpeg -framerate 30 -i frame_%04d.png -c:v libx264 -pix_fmt yuv420p output.mp4这条命令的意思是输入帧率 30输入文件是 frame_0001.png 到 frame_0150.png视频编码用 libx264像素格式用 yuv420p输出 output.mp4。其中-pix_fmt yuv420p非常重要因为很多播放器和平台只支持这种像素格式不加这个参数可能导致视频在某些设备上无法播放。如果你需要控制视频质量可以加-crf参数。CRF 是恒定速率因子范围 0 到 51数值越小质量越高、文件越大。一般用 18 到 23 之间比较合适。18 接近无损23 是默认值文件大小和质量比较平衡。如果需要压缩成 H.265 编码可以用-c:v libx265但兼容性不如 H.264需要根据目标平台决定。如果视频要上传到大多数社交平台H.264 是最稳妥的选择。3. 核心细节解析与实操要点3.1 环境准备无头浏览器和 FFmpeg 的安装在开始之前你需要准备两个核心工具一个无头浏览器环境和一个 FFmpeg。无头浏览器推荐用 Playwright因为它对 Chromium、Firefox、WebKit 都有支持API 也比较友好。安装方式很简单npm init -y npm install playwright npx playwright install chromiumFFmpeg 的安装根据系统不同有所区别。在 Ubuntu 上可以直接用 aptsudo apt update sudo apt install ffmpeg在 macOS 上可以用 Homebrewbrew install ffmpeg在 Windows 上可以去官网下载编译好的二进制文件然后把 bin 目录加到 PATH 里。安装完成后在命令行输入ffmpeg -version如果能输出版本信息就说明安装成功了。注意Playwright 安装 Chromium 的时候会下载一个比较大的浏览器包如果网络环境不好可能需要多试几次。另外FFmpeg 的版本建议用 4.0 以上老版本对某些编码参数支持不好。3.2 页面结构设计让每一帧都可控要让 hyperframes 方案跑通HTML 页面的结构需要专门设计。核心原则是所有动态内容都必须由帧号驱动不能依赖自动播放的动画。具体来说页面里应该有一个全局的时间轴控制接口比如window.setFrame function(frameIndex) { const time frameIndex / FPS; // 根据 time 更新所有元素状态 updateElements(time); // 强制重绘 return new Promise(resolve { requestAnimationFrame(() resolve()); }); };这个setFrame函数接收帧号计算出对应的时间然后更新页面。返回一个 Promise 是为了让截取脚本知道“页面已经更新完毕可以截图了”。如果没有这个 Promise截图可能发生在 DOM 更新之前导致拿到旧画面。页面里的动画元素建议用绝对定位通过transform: translate()和opacity来控制。这两个属性不会触发浏览器的布局重排性能更好而且渲染结果更稳定。避免使用display切换或者width/height动画因为这些会触发重排可能导致截图时画面不一致。3.3 截取脚本编写逐帧截图的完整流程截取脚本是整个方案的核心。下面是一个基于 Playwright 的完整示例const { chromium } require(playwright); const fs require(fs); const path require(path); const FPS 30; const DURATION 5; // 秒 const TOTAL_FRAMES FPS * DURATION; const WIDTH 1920; const HEIGHT 1080; const OUTPUT_DIR ./frames; async function capture(htmlPath) { const browser await chromium.launch(); const page await browser.newPage({ viewport: { width: WIDTH, height: HEIGHT } }); await page.goto(file:// path.resolve(htmlPath)); await page.waitForLoadState(networkidle); if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } for (let i 0; i TOTAL_FRAMES; i) { await page.evaluate((frame) window.setFrame(frame), i); const filename frame_${String(i).padStart(4, 0)}.png; await page.screenshot({ path: path.join(OUTPUT_DIR, filename), type: png }); if (i % 30 0) { console.log(已截取 ${i}/${TOTAL_FRAMES} 帧); } } await browser.close(); } capture(./template.html).then(() { console.log(截帧完成); });这段脚本做的事情很清晰启动浏览器打开 HTML 文件循环调用setFrame每次截图保存成 PNG。文件名用四位数字编号方便 FFmpeg 按顺序读取。有几个细节需要注意。第一waitForLoadState(networkidle)确保页面所有资源加载完毕再开始截取否则可能截到空白画面。第二page.evaluate是异步的它会等待setFrame返回的 Promise resolve 之后再继续这样能保证截图时页面已经更新。第三截图格式用 PNG 而不是 JPEG因为 PNG 是无损的后续编码成视频时画质更好。3.4 参数计算帧率、时长、分辨率怎么定帧率的选择直接影响视频的流畅度和文件大小。24fps 是电影的标准帧率适合有电影感的画面。30fps 是大多数网络视频的标准兼容性最好。60fps 适合游戏录制或者高速运动画面但文件会大很多。对于 hyperframes 这种用 HTML 渲染的场景30fps 通常是最佳选择因为浏览器渲染一帧需要时间60fps 可能导致截取速度跟不上。时长根据内容需求定。如果是做一个 10 秒的动效展示那就是 300 帧。如果是做一个 1 分钟的产品介绍那就是 1800 帧。帧数越多截取和编码的时间越长。以 1920x1080 分辨率为例截取一帧大约需要 50 到 100 毫秒1800 帧大概需要 2 到 3 分钟。编码阶段 FFmpeg 处理 1800 帧大约需要 30 秒到 1 分钟。整体时间是可以接受的。分辨率的选择要考虑目标平台。1920x1080 是通用选择3840x2160 适合高质量展示1080x1920 适合竖屏短视频。需要注意的是分辨率越高浏览器渲染和截图的时间越长。如果只是做草稿预览可以先用 1280x720 快速验证最终输出再切到高分辨率。提示在计算总帧数时建议用Math.round(FPS * DURATION)而不是直接相乘避免浮点数精度问题导致少一帧或多一帧。4. 实操过程与核心环节实现4.1 从零搭建一个可截帧的 HTML 模板下面用一个实际例子来演示整个流程。假设我们要做一个简单的文字动画视频一段标题从左侧滑入然后淡出一段副标题。整个动画持续 3 秒30fps总共 90 帧。首先创建 HTML 文件!DOCTYPE html html langzh-cn head meta charsetutf-8 titlehyperframes demo/title style * { margin: 0; padding: 0; box-sizing: border-box; } body { width: 1920px; height: 1080px; overflow: hidden; background: #0a0a0a; font-family: sans-serif; } .title { position: absolute; top: 400px; left: 0; font-size: 120px; color: #ffffff; opacity: 0; transform: translateX(-200px); } .subtitle { position: absolute; top: 600px; left: 0; font-size: 48px; color: #888888; opacity: 0; transform: translateX(-100px); } /style /head body div classtitleHyperframes/div div classsubtitle用 HTML 做视频/div script const FPS 30; const titleEl document.querySelector(.title); const subtitleEl document.querySelector(.subtitle); function easeOut(t) { return 1 - Math.pow(1 - t, 3); } window.setFrame function(frameIndex) { const time frameIndex / FPS; // 标题0 到 1 秒滑入 const titleProgress Math.min(time / 1, 1); const titleEased easeOut(titleProgress); titleEl.style.opacity titleEased; titleEl.style.transform translateX(${-200 200 * titleEased}px); // 副标题1 到 2 秒滑入 const subtitleProgress Math.min(Math.max((time - 1) / 1, 0), 1); const subtitleEased easeOut(subtitleProgress); subtitleEl.style.opacity subtitleEased; subtitleEl.style.transform translateX(${-100 100 * subtitleEased}px); return new Promise(resolve { requestAnimationFrame(() resolve()); }); }; /script /body /html这个模板的关键点在于所有动画状态都由time计算得出而time来自frameIndex。easeOut函数让动画有缓动效果看起来更自然。setFrame返回 Promise确保截图前页面已经完成重绘。4.2 执行截帧和编码的完整命令把上面的 HTML 保存为template.html截取脚本保存为capture.js然后执行node capture.js脚本会在frames目录下生成 90 张 PNG 图片。接下来用 FFmpeg 合成视频ffmpeg -framerate 30 -i frames/frame_%04d.png \ -c:v libx264 -pix_fmt yuv420p -crf 20 \ -movflags faststart output.mp4这里多了一个-movflags faststart参数。它的作用是把视频的元数据移到文件开头这样视频在网页上可以边加载边播放不用等整个文件下载完。如果你要把视频放到网站上这个参数很有用。执行完这条命令output.mp4就是最终视频。用播放器打开应该能看到标题滑入、副标题跟进的效果。4.3 批量生产从单个视频到流水线单个视频跑通之后批量生产就简单了。你可以把 HTML 模板参数化比如把标题文字、颜色、动画时长做成变量然后用脚本批量生成 HTML 文件再批量截帧和编码。一个常见的做法是用模板引擎比如 Handlebars 或者 EJS把数据注入 HTML 模板。然后写一个主控脚本遍历数据列表对每一条数据生成 HTML、截帧、编码、输出 MP4。整个过程可以完全自动化。如果你用 AI coding agents 来生成 HTML那批量生产就更轻松了。你可以让 AI 根据一段文案生成对应的 HTML 动画页面然后直接丢给截帧脚本。这样从文案到视频的链路就打通了中间不需要人工干预。注意批量生产时要注意磁盘空间。90 帧 1920x1080 的 PNG 大约占用 200 到 300 MB如果批量处理 100 个视频中间帧文件可能占用几十 GB。建议每处理完一个视频就清理帧文件或者把帧文件写到临时目录。5. 常见问题与排查技巧实录5.1 截图空白或画面不完整这是最常见的问题。原因通常有三种页面资源没加载完、截图时机太早、viewport 尺寸不对。页面资源没加载完的典型表现是截图里只有背景色文字和图片都没出来。解决办法是在page.goto之后加waitForLoadState(networkidle)确保所有网络请求都完成了。如果页面里有异步加载的内容还可以加一个waitForTimeout等待一段时间。截图时机太早的表现是画面停留在初始状态动画没有更新。这通常是因为setFrame没有返回 Promise或者截图脚本没有等待 Promise。检查setFrame是否返回了 Promise以及page.evaluate是否 await 了这个 Promise。viewport 尺寸不对的表现是画面被裁剪或者有黑边。检查newPage时的viewport设置是否和 HTML 里body的尺寸一致。如果 HTML 里写的是 1920x1080viewport 也必须是 1920x1080。5.2 视频播放卡顿或不同步视频卡顿通常和帧率有关。如果你截取的时候帧率不稳定比如有些帧花了 200 毫秒有些帧只花了 50 毫秒那合成出来的视频虽然标称 30fps但实际播放时会有节奏问题。解决办法是确保每一帧的截取时间尽量一致。可以在截图前加一个固定的等待时间或者用page.screenshot的animations: disabled选项禁用页面自身的动画。另一个可能的原因是 FFmpeg 的帧率参数和实际帧数不匹配。比如你截了 90 帧但 FFmpeg 命令里写的是-framerate 60那视频就会变成 1.5 秒速度不对。检查-framerate是否和截帧时的 FPS 一致。5.3 中文字体渲染异常在无头浏览器里渲染中文时可能会遇到字体缺失或者显示成方块的问题。这是因为无头浏览器默认可能没有安装中文字体。解决办法是在系统里安装中文字体包或者在 HTML 里用font-face引入 web 字体。在 Ubuntu 上安装中文字体sudo apt install fonts-noto-cjk在 HTML 里指定字体body { font-family: Noto Sans CJK SC, Microsoft YaHei, sans-serif; }如果用了 web 字体确保字体文件在截帧之前加载完成。可以在setFrame之前加一个document.fonts.ready的等待。5.4 常见问题速查表问题现象可能原因排查方法解决方案截图全黑或全白页面未加载完检查 networkidle加 waitForLoadState画面停留在初始状态setFrame 未生效检查 Promise 返回值确保 await evaluate画面被裁剪viewport 尺寸不对对比 body 尺寸统一设置为相同值视频播放速度不对帧率参数不匹配检查 framerate统一 FPS 设置中文显示为方块字体缺失查看截图安装中文字体视频文件过大CRF 值太低检查 crf 参数调到 23 到 28视频无法在某些平台播放像素格式不兼容检查 pix_fmt用 yuv420p截帧速度太慢分辨率太高降低分辨率测试先用 720p 验证5.5 实操心得几个让我少走弯路的技巧第一个技巧是先用低分辨率跑通全流程。我一开始就直接上 4K结果截一帧要 500 毫秒90 帧花了 45 秒调试起来非常痛苦。后来改成 1280x720截一帧只要 30 毫秒整个流程几秒钟就跑完了。确认逻辑没问题之后再切到高分辨率输出。第二个技巧是把帧文件写到内存盘。在 Linux 上可以用/dev/shm目录它是基于内存的读写速度比硬盘快很多。对于 90 帧这种小批量直接把帧文件写到/dev/shm/frames截帧和编码的速度都会明显提升。第三个技巧是给 FFmpeg 加-threads参数。默认情况下 FFmpeg 会用所有可用的 CPU 核心但有时候手动指定线程数效果更好。比如-threads 4可以限制在 4 个核心避免和其他任务抢资源。第四个技巧是保留中间帧文件。虽然占空间但如果视频有问题你可以直接检查某一帧的 PNG看看是截帧的问题还是编码的问题。如果 PNG 正常但视频有问题那就是 FFmpeg 参数的问题如果 PNG 本身就不对那就是页面或截帧脚本的问题。6. 进阶玩法和 AI coding agents 结合6.1 用 AI 生成 HTML 动画模板AI coding agents 现在写 HTML 动画已经相当靠谱了。你可以给一个描述比如“做一个 3 秒的标题动画文字从下方弹入带一点回弹效果背景是深色渐变”AI 就能生成对应的 HTML CSS JS 代码。生成之后你只需要检查setFrame接口是否暴露出来然后丢给截帧脚本。这里的关键是给 AI 一个明确的约束所有动画必须由window.setFrame(frameIndex)驱动不能依赖自动播放。你可以在 prompt 里直接写清楚这个要求AI 通常会遵守。如果 AI 生成的代码不符合要求你可以让它修改或者自己手动调整。6.2 从文案到视频的自动化链路把 AI 生成 HTML 和 hyperframes 截帧结合起来可以搭一条从文案到视频的自动化链路。流程大概是输入一段文案AI 生成对应的 HTML 动画页面截帧脚本把页面变成帧序列FFmpeg 把帧序列编码成 MP4。整个过程可以在一个脚本里串起来输入文案输出视频文件。这条链路的价值在于它把视频制作的门槛降到了“会写文案”的程度。你不需要会剪辑不需要会设计甚至不需要会写代码只要能把需求描述清楚剩下的交给工具。对于做批量内容生产的人来说这意味着效率的质变。6.3 和 CLI 工具的配合hyperframes 方案里的截帧和编码都是命令行工具这意味着它可以很容易地和其他 CLI 工具配合。比如你可以用zcode cli或者codex cli来生成 HTML 模板用gitlab cli来管理版本用openspec cli来管理项目配置。整个工作流都在命令行里完成非常适合自动化和持续集成。如果你用codex cli它有一些命令比如/compact、/model、/resume可以管理会话。你可以在一个会话里让 AI 生成 HTML然后直接在当前目录下运行截帧脚本不需要切换工具。这种流畅的体验是纯图形界面工具很难做到的。提示在自动化链路里建议给每个视频生成一个唯一的 ID用这个 ID 来命名 HTML 文件、帧目录和输出视频。这样可以避免文件覆盖也方便追溯问题。7. 性能优化与输出质量控制7.1 截帧速度优化截帧速度主要受三个因素影响分辨率、页面复杂度、浏览器启动开销。分辨率越高截图越慢。页面越复杂渲染越慢。浏览器启动开销是固定的但如果批量处理多个视频可以复用同一个浏览器实例避免反复启动。复用浏览器实例的做法是在批量脚本里只启动一次浏览器然后为每个视频创建一个新的 page处理完之后关闭 page最后再关闭浏览器。这样可以把浏览器启动的开销分摊到多个视频上。页面复杂度方面尽量减少 DOM 节点数量避免复杂的 CSS 滤镜和阴影。如果页面里有大量元素可以考虑用 Canvas 绘制因为 Canvas 的渲染性能通常比 DOM 好。7.2 视频质量控制视频质量主要由 CRF 参数控制。CRF 越低质量越高文件越大。对于文字动画这种画面CRF 18 到 20 通常就够了因为文字边缘比较锐利不需要太高的码率。对于有渐变和阴影的画面CRF 可以稍微低一点比如 16 到 18避免出现色带。如果视频要上传到社交平台建议先了解一下平台的推荐参数。大多数平台推荐 H.264 编码、AAC 音频、yuv420p 像素格式、30fps 或 60fps。按照这些参数输出兼容性最好。7.3 音频处理hyperframes 方案默认只处理视频不处理音频。如果你的视频需要背景音乐或者旁白可以在 FFmpeg 编码的时候加音频输入ffmpeg -framerate 30 -i frames/frame_%04d.png \ -i audio.mp3 \ -c:v libx264 -pix_fmt yuv420p -crf 20 \ -c:a aac -b:a 192k -shortest \ output.mp4这里-i audio.mp3是音频输入-c:a aac指定音频编码为 AAC-b:a 192k指定音频码率 192kbps-shortest表示视频和音频取较短的时长。如果音频比视频长会被截断如果音频比视频短视频会在音频结束后继续播放静音。8. 适用场景与边界hyperframes 方案最适合的场景是用 HTML 描述画面、需要批量生产、对帧率精度有要求的视频制作。比如数据可视化动画、产品介绍视频、社交媒体短视频、教学演示动画。这些场景的共同特点是画面元素可以用代码描述不需要实拍素材。它不太适合的场景是需要实拍视频、需要复杂剪辑、需要专业调色的项目。这些场景还是得用传统视频工具。hyperframes 的定位是“用代码生成视频”而不是“替代所有视频制作工具”。另外hyperframes 方案对开发者的技术要求比传统视频工具高。你需要会写 HTML、CSS、JS需要会用命令行需要理解帧率和编码参数。如果你完全不想碰代码那这个方案可能不适合你。但如果你有前端基础或者愿意让 AI 帮你写代码那这个方案的上手门槛其实并不高。我个人在实际操作中的体会是hyperframes 最大的价值不是“省事”而是“可控”。传统视频工具里你想精确控制某一帧的画面得手动拖时间轴、调参数很难做到像素级精确。而用代码控制每一帧都是计算出来的想改哪里就改哪里想复现就复现。这种可控性在批量生产和自动化场景里是决定性的优势。最后再分享一个小技巧如果你要做的视频有多个场景可以把每个场景写成一个独立的 HTML 文件分别截帧然后用 FFmpeg 的 concat 功能拼接。这样每个场景可以独立调试互不影响。拼接命令大概是ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4其中list.txt里列出每个视频文件的路径。这种方式比把所有场景塞进一个 HTML 文件要清晰得多也更容易维护。
返回列表