内容
# 🎬 Screenwright
> **带字幕的教程视频,脚本化。** 一个 [MCP](https://modelcontextprotocol.io) 服务器,通过驱动一个真正的 **浏览器** ([Playwright](https://playwright.dev)) *或* **安卓/Flutter 模拟器** (`adb`),将一系列步骤转化为旁白屏幕录制。字幕 **烧录到视频中** *和* 以 `.srt` 文件导出。
名字的由来是 **Playwright** (引擎)+ *屏幕*。
```
步骤[] ──► Playwright 驱动浏览器 ──► 同步字幕覆盖每个步骤
──► 视频录制 ──► ffmpeg → .mp4 + .srt 副文件
```
---
## ✨ 功能
- **脚本化教程** — `goto`, `click`, `fill`, `type`, `press`, `hover`, `scroll`, `wait`.
- **同步字幕** — 为任意步骤附加 `caption`;它被烧录到视频中并写入定时 `.srt`.
- **自包含输出** — 捆绑 `ffmpeg` (通过 `ffmpeg-static`)生成干净的 H.264 `.mp4`.
- **健壮** — 每个操作超时;标记一个步骤 `optional`,这样缺少的选择器不会中止录制。
- **网页 *和* 移动端** — Playwright 用于网页;`adb` `screen-record` + ffmpeg 字幕烧录用于 **Android / Flutter** 应用(无需应用源代码)。
- **从 AI(MCP 工具)或直接从 Node 使用**。
## 📦 需求
- Node.js **18+**
- Playwright 的 Chromium 版本:`npx playwright install chromium` (在 `npm install` 时自动运行)。
## 🚀 安装
```bash
# 从 GitHub
npm install -g github:0xjesus/screenwright
# 或克隆
git clone https://github.com/0xjesus/screenwright.git
cd screenwright && npm install
```
## 🔌 用作 MCP 服务器
将其添加到您的 MCP 客户端。**Claude Desktop / Claude Code** (`claude_desktop_config.json` 或 `.mcp.json`):
```json
{
"mcpServers": {
"screenwright": {
"command": "node",
"args": ["/绝对路径/to/screenwright/src/index.js"]
}
}
}
```
(如果全局安装,可以使用 `"command": "screenwright"`,无需参数。)
然后只需让您的助手录制教程 — 它会调用 **`record_tutorial`** 工具。
### 工具:`record_tutorial`
| 字段 | 类型 | 备注 |
|---|---|---|
| `output` | 字符串 | 输出 `.mp4` 的路径。 |
| `steps` | step[] | 有序步骤(如下)。 |
| `baseUrl` | 字符串? | 以便 `goto` 步骤可以使用相对路径。 |
| `viewport` | `{width,height}`? | 默认 `1440×900`。 |
| `headless` | 布尔? | 默认 `true`。 |
| `channel` | 字符串? | 例如 `"chrome"` 以使用系统浏览器。 |
| `burnIn` | 布尔? | 将字幕烧录到视频中。默认 `true`。 |
| `srt` | 字符串? | 自定义 `.srt` 路径。默认 `<output>.captions.srt`。 |
| `captionStyle` | 对象? | `{ position, fontSize, bg, color, maxWidth }`。 |
**步骤** = `{ caption?, action, url?, selector?, text?, key?, deltaY?, delayMs?, timeoutMs?, dwellMs?, optional? }`。
`selector` 是任意 Playwright 选择器 — CSS,`text=…`,`xpath=…`,或 `:has-text(…)`。
### 工具:`record_android_tutorial` 📱
同样的想法,用于 **Flutter / Android 应用在模拟器或设备上**。字幕无法注入到原生应用中,因此屏幕使用 `adb screenrecord` 记录,字幕随后使用 ffmpeg(libass)从同步的 `.srt` 中烧录。
**要求:** Android 平台工具 (`adb`) + **正在运行的模拟器/设备** (它必须显示在 `adb devices` 中)。对于 Flutter:`flutter emulators --launch <id>`,然后运行您的应用。
| 字段 | 备注 |
|---|---|
| `output` | 输出 `.mp4`。 |
| `steps` | 有序步骤(如下)。 |
| `serial` | 当连接多个设备时,使用 `adb -s` 序列号。 |
| `size` | 录制大小 `"WxH"` (默认:设备分辨率)。 |
| `bitRate` · `srt` · `burnIn` · `adbPath` · `captionStyle` | 可选。 |
**步骤操作** (坐标为 **设备像素** ) — 每个操作可能带有 `caption` 和 `dwellMs`:
- `tap` — `{ x, y }`
- `text` — `{ text }`
- `swipe` — `{ x1, y1, x2, y2, durationMs? }`
- `key` — `{ key }` (`BACK`, `HOME`, `ENTER`, `MENU`, `APP_SWITCH`, 或 `KEYCODE_*`)
- `launch` — `{ package, activity? }`
- `wait` — `{ dwellMs }`
参见 **`examples/android-flutter.json`**。从 Node:`import { recordAndroidTutorial } from 'screenwright/android'`。
## 🧪 从 Node 使用(无 MCP)
```bash
node scripts/run-example.js # 记录 examples/demo.json
node scripts/run-example.js examples/capleton.json
```
```js
import { recordTutorial } from 'screenwright/recorder';
await recordTutorial({
output: 'out/tour.mp4',
baseUrl: 'https://playwright.dev',
steps: [
{ action: 'goto', url: '/', caption: '欢迎参加本次教程 🎬', dwellMs: 2600 },
{ action: 'scroll', deltaY: 600, caption: '每个步骤都可以带有同步字幕…', dwellMs: 2400 },
{ action: 'goto', url: '/docs/intro', caption: '…烧录到视频中并导出为 .srt', dwellMs: 3000 },
],
});
// → { mp4, srt, durationMs, steps, captions }
```
## 💡 提示
- **不要重复字幕。** `.mp4` 已经有烧录的字幕。像 VLC 这样的播放器会自动加载与视频同名的 `.srt`,并将其绘制在 **顶部**。Screenwright 默认将副文件设为 `*.captions.srt` (不匹配的名称),因此不会发生这种情况 — 保持不变,或在播放器中禁用字幕轨道。想要仅可选择的字幕?传递 `burnIn: false` 以获得干净的视频 + `.srt`。
- **Linux 上 VLC 显示黑屏?** 那是 GPU/输出故障,不是文件。使用 `vlc --avcodec-hw=none --vout=xcb_x11` 启动,或在 VLC → 首选项中设置。
- **无显示仍然记录** — 无需显示。
## 📝 许可证
MIT © 0xjesus