mcpField
F
frame-capture

frame-capture

github.com/moh4696创意与媒体377221 次安装5 天前更新
代码仓库

关于 frame-capture

frame-capture 是一项通过虚拟时钟和逐帧截图录制网页视频的技能,适合需要精确控制滚动编排的开发者。即使场景渲染较慢,也能生成稳定帧率的视频,并可制作片段对比。

主要功能

  1. 01将 URL 录制为 MP4
  2. 02控制滚动和指针移动
  3. 03逐帧推进虚拟时钟
  4. 04使用 Chromium 或 WebKit 捕获
  5. 05制作带标签的片段对比

适用场景

  1. 01录制网页滚动过程
  2. 02避免重型动画场景录制时卡顿
  3. 03对比两个网页或模型的输出

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/moh4696/open-3d-skills --skill frame-capture

安装后在 Claude Code 中输入/frame-capture确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
scripts/
compare.py
record.py
serve.py

详细介绍

帧捕获

屏幕录制工具会实时捕获 GPU 成功绘制的内容,因此场景一复杂就会卡顿,滚动过程看起来也像手持拍摄。本工具采用不同的录制方式。在页面自身的脚本运行之前,它会替换页面时钟:performance.now、Date.now 和 requestAnimationFrame 都会读取虚拟时间,CSS 动画和过渡效果也会固定在虚拟时间上,并将每个 <video> 暂停并定位到对应时间。每输出一帧,时钟就恰好前进 1/60 秒,运行一帧并截取屏幕。即使一帧需要两秒才能渲染,视频仍会以完美的 60 fps 播放。

工具

脚本用途
scripts/record.py使用滚动按键、指针移动和就绪条件,将 URL 录制为 MP4
scripts/compare.py堆叠两个片段(或将它们并排放置),并添加标签和圆角面板
scripts/serve.py静态服务器,可响应 HTTP Range 请求,以便视频进行定位

需要 Python 3.9+、pip install playwright pillow、python3 -m playwright install chromium webkit,以及 PATH 中的 ffmpeg。

运行

  1. 使用 scripts/serve.py 提供页面服务,切勿使用 python3 -m http.server。内置服务器会忽略 Range 请求,导致浏览器无法定位它所提供的任何视频(video.seekable 为空),录制的视频每次都会停留在首帧。record.py 检测到此情况时会发出警告。

    python3 scripts/serve.py path/to/site --port 8000
    
  2. 先快速试跑一次。 每秒 10 帧可以在几秒钟内看完整个编排,而不是花上几分钟:

    python3 scripts/record.py http://127.0.0.1:8000/ /tmp/check.mp4 --seconds 20 --fps 8 \
      --scroll "0:0 2.5:0 9:40% 12:40% 19:100%" --pointer drift
    

观看效果、调整按键,再重复试跑。只有确认后才渲染完整片段。

  1. 渲染最终版本。 --size 设置 CSS 视口大小,--dpr 用于放大视口。--size 1920x1080 --dpr 1 会生成 1080p;--size 1280x720 --dpr 1.5 会生成相同的 1920x1080 画面,但布局更大。输出采用 H.264、CRF 16、yuv420p、BT.709 标签、faststart,且无音频。

    python3 scripts/record.py http://127.0.0.1:8000/ out.mp4 --seconds 20 --fps 60 \
      --scroll "0:0 2.5:0 9:40% 12:40% 19:100%" --pointer drift --ready "window.__ready === true"
    
  2. 交付前查看结果。 在关键时刻提取帧(ffmpeg -ss 9 -i out.mp4 -frames:v 1 f.png)并检查:首帧、每次滚动停顿,以及末帧。

编排
  • --scroll 的按键格式为 秒数:位置。位置可以是像素值(1200)、滚动范围的比例(40%),也可以是视口高度数(2.5vh)。各段采用缓动效果(半程线性、半程 smootherstep,因此长距离移动不会在中途突然加速)。在线性移动的时间后加上 ~:9~:60%。
  • 需要让观众阅读的内容都应停留足够时间:为固定区块或计数器添加一组位置相同的按键。
  • --pointer drift 会让真实鼠标缓慢地绕屏幕中心移动,使悬停状态、视差效果和跟随光标的装置动起来。--pointer 0.7,0.3 会将光标固定在该位置。
  • 对于页面最了解如何编排的内容(如镜头飞行、导览),让页面自行驱动:在 ?record=1 标记下定义 window.__recordFrame = (t) => { ... }。每帧开始前都会调用该函数,传入以秒为单位的虚拟时间。录制期间 window.__recording 为 true。
  • 平滑滚动库会与设置滚动位置的录制器冲突。--kill-lenis 会阻止 Lenis 加载。对于其他库,请在 ?record=1 下将其关闭。

让页面支持录制

  • 时间必须来自 performance.now() 或 rAF 时间戳,不能来自 setTimeout 或 setInterval。 虚拟时钟运行时,计时器仍会按真实时间运行,因此 setTimeout(next, 3000) 会在三秒真实时间后触发,此时可能是第 20 帧,也可能是第 400 帧。应改为基于页面时钟安排:

    const pending = [];
    const later = (secs, fn) => pending.push({ at: performance.now() / 1000 + secs, fn });
    // in the frame loop:
    const now = performance.now() / 1000;
    for (let i = pending.length - 1; i >= 0; i--) if (now >= pending[i].at) pending.splice(i, 1)[0].fn();
    
  • 暴露一个就绪标记(首帧渲染完成、纹理解码、字体加载后设置 window.__ready = true),并通过 --ready 传入。资源加载完成前就开始录制,会让加载闪烁被烙进第 0 帧。

  • 在录制模式下,隐藏影片中不会出现的界面元素:提示、光标、加载器和 Cookie 栏。

  • 如果 WebGL 输出的帧是黑屏或过时画面,请在录制时使用 preserveDrawingBuffer: true 创建渲染器。

浏览器

  • **Chromium(默认)**会在无头模式下使用真实 GPU 运行 WebGL。在 macOS 上,脚本会添加 --use-angle=metal,以全速渲染;不加此参数时,Chromium 会回退到 SwiftShader。虽然效果正确,但速度会慢很多倍。
  • WebKit(--browser webkit)可展示 Safari 的渲染效果:字体平滑、色彩处理和视频解码都各不相同。它在 1080p 下偶尔会卡住截图(约每 100 次出现 1 次);脚本会重试,而且由于步骤之间时钟处于暂停状态,重试会返回完全相同的帧。
  • 如果缺少 Playwright 自带的 Chromium(升级后版本不匹配),脚本会在 Playwright 缓存中查找最新版本的 Chromium。CHROME_PATH 可覆盖该路径。
  • 切勿在你看不到的可见浏览器标签页中录制,也不要在隐藏的嵌入式预览窗格中录制。后台标签页会限制或冻结 requestAnimationFrame。无头模式则不会。

比较

python3 scripts/compare.py a.mp4 b.mp4 versus.mp4 --labels "Model A" "Model B"            # stacked, for phones
python3 scripts/compare.py a.mp4 b.mp4 versus.mp4 --labels "Before" "After" --layout side   # side by side

公平的比较应保持所有条件一致,只有被比较的内容不同:

  • 使用相同的视口、相同的时长和相同的动画编排(原样复用 --scroll 键)。
  • 先将每个来源裁剪到只包含其内容。移除另一段视频中没有的水印、网络摄像头叠层和 UI 边框。
  • 输出静音视频。两段音轨会相互干扰,音频也会分散对画面的注意力。
  • 较短的视频停留在最后一帧,这样两段视频就会同时结束。
  • 在标签中如实标明两侧的内容。把观众熟悉的那一侧放在上方。

交付

  • 社交平台会重新编码所有内容。分辨率为 1920x1080 或 1080x1920、帧率为 60 fps、编码格式为 H.264、CRF 为 14 到 18 的视频最能经受重新编码。更高分辨率通常也会被缩小。
  • 保留母版。使用 ffmpeg 从母版制作精简版(6 s 循环视频、竖屏裁剪版),而不要重新录制。
  • 之后再添加声音,并根据录制时打印的帧数确定时间。切勿通过虚拟时钟录制音频。

评论

支持 Markdown