内容
="center">
<="watch-it.png" alt="Watch" width="640">
>
<h1 align="center">Watch</h1>
<pcenter">
<strong>一个赋予AI编码代理视觉服务器。</strong><br>
将任何屏幕录制转化为结构化时间线,供代理推理。
</p>
<p align="center <a href="#安装">安装</a> ·
<="#配置">配置</a> ·
<a href="#使用</a> ·
<a href="#工作原理">工作原理</ ·
<a href="#">路线图</a>
</p>
---
像 **Claude Code**、**Codex** 和 **Cursor** 这样的编码代理能够很好地推理文本、代码和图像,但它们对视频却视而不见。开发人员经常分享错误、演示和教程的屏幕录制。**Watch** 弥补了这一空白:它分析视频并返回**语义事件**,而不是逐帧转储,以便代理能够回答实际发生> AI编码代理了大脑。**予了它们视觉。视频 → Watch → 结构化观察 → Claude Code → 推```
## 您将获得
一个紧凑、结构化的时间线,而不是成千上万个帧 token:
```json "video_id": "f8c1d29e07f5",
duration": "02:13 "events": [
timestamp": "00:05type": "navigation",": "开发者打开 localhost:3000" },
{": "00:18", "type": "interaction", "description": "点击提交按钮" },
"timestamp": "00:22", "type": " "description": "控制台显示 HTTP 500" }
],
"cost": { "usd": 0.000097, "prompt_tokens": 416, "": 128, "model": "qwen/qwen3-32b-instruct", "calls": 1 }
}
cost` 报告来自实际使用情况(通过 Open会计);对于 `mode="manual"` 和 `get_frames`没有模型调用,因此为 `null`。
事件` 是以下之一:`navigation`、`interaction`、`error`、`ui_change`、`terminal`、`network`、`loading`、`dialog`、`code_edit``。
## 工具
**`watch(video query=None, mode="sample", start=None,)`** — 分析视频上述时间线和_id`。模式:
| 模式 | 功能 | 成本 |
| --- | --- | --- |
| `sample`(默认) | AI 扫描场景采样帧 → 时间线 | 便宜,固定 |
| `manual` | — 只是缓存视频,返回 `video_id `duration`,以便代理自己检查帧 | 零 |
| `full` | 将整个剪辑发送到视频原生模型(`start`/`end` 先修剪) | 随持续时间缩放 |
`full` 需要一个 **支持视频** 的端点。在 OpenRouter 上,这意味着例如 `qwen/qwen3.5-*`、`qwen/qwen3.6-*` 或 `xiaomi/mimo-v2.5` — `qwen2.5-vl` / `qwen3-vl` 系列仅支持图像,仅适用于 `sample`。
**`get_frames(video start, end=None, max_frames=8)`** — 从您已经观看过的视频中提取实际帧图像。代理的眼睛,当它怀疑时间线或用户指向确切时刻时使用。由内容地址缓存支持,因此不会重新下载。
## 功能
- 🎥 **本地文件** — `.mp4`、`.mov`、`.webm`、`.mkv`、`.avi`、`.m4v`
- 🔗 **托管 URL** — Loom、ScreenPal、Vimeo(公共)、直接 MP4
- 🧠 **模型无关** — 任何 OpenAI 兼容的视觉端点(本地 vLLM Qwen2.5-VL、DashScope、OpenRouter 等)
- ✂️ **场景感知采样** — 只有有意义的时刻才会传递给模型,保持输出和 token 成本小
- 👁️ **按需帧** — `get_frames` 允许代理在摘要不够时查看确切像素
- 🗄️ **内容地址缓存** — 重复观看和帧拉取会重用已解析的视频;重启后仍然有效
- 💰 **每次调用成本跟踪** — 每个 `watch` 结果都会报告模型调用的实际 USD + token 使用情况
- 🔌 **Stdio MCP** — 与任何 MCP 客户端配合使用
## 安装
**要求:** Python 3.11+ 和 [FFmpeg](https://ffmpeg.org/)(解码视频,合并 Loom/ScreenPal 流)。
```bash
# 1. FFmpeg
winget install Gyan.FFmpeg # Windows (macOS: brew install ffmpeg · Linux: apt install ffmpeg)
# 2. 克隆并安装
git clone https://github.com/ManzarAli25/watch-it.git
cd watch-it
python -m venv .venv
# Windows: .\.venv\Scripts\Activate.ps1 · macOS/Linux: source .venv/bin/activate
pip install -e ".[dev]"
# 3. 配置
cp .env.example .env # 然后编辑(或保留 WATCH_VLM_MODEL=stub 进行离线测试)
```
## 配置
Watch 与任何 **OpenAI 兼容的视觉端点** 通信。在 `.env` 中设置:
| 变量 | 描述 |
| --- | --- |
| `WATCH_VLM_BASE_URL` | 例如 `http://localhost:8000/v1`(本地 vLLM)或托管的兼容端点 |
| `WATCH_VLM_MODEL` | 例如 `Qwen/Qwen2.5-VL-7B-Instruct`。设置为 `stub` 进行离线、无密钥的测试运行 |
| `WATCH_VLM_API_KEY` | 承载令牌(如果您的端点需要) |
可选调整:`WATCH_VLM_MAX_TOKENS`、`WATCH_MAX_FRAMES`、`WATCH_FRAME_MAX_EDGE`、`WATCH_SCENE_THRESHOLD`、`WALLBACK_INTERVAL`、`_MAX_DURATION`、`WATCH_GET_FRAMES_MAX`、`WATCH_CACHE_TTL`、`WATCH_CACHE_MAX_BYTES`。
## 使用
Watch 作为_stdio MCP 服务器运行(`python -m watch_mcp.server`),因此任何具有 MCP 功能的代理都可以使用以下注册您的客户端,然后录制:
```
为什么我的 React 模态窗口关闭了?
[bug.mp4]
```
代理调用 `watch(video_path="bug.mp4", query="为什么我的 React 模态窗口关闭了?")`,推理返回的时间线,并且可以 `get_frames(video_id, "00:22")` 查看任意时刻。
> 使用虚拟环境的 **绝对路径** 到 `python`(例如 Windows 上的 `.venv/Scripts/python.exe`,macOS/Linux 上的 `.venv/bin/python`),以便服务器使用正确的依赖项启动,而不管客户端的工作目录如何。
### Claude Code
```bash
claude mcp add watch-it -- /path/to/.venv/bin/python -m watch_mcp.server
```
### Cursor
添加到 `.cursor/mcp.json`(项目)或 `~/.cursor/mcp.json`(全局):
```json
{
"mcpServers": {
"watch-it": {
"command": "/path/to/python",
"args": ["-m", "watch_mcp.server"]
}
}
}
```
然后在 *设置 → MCP* 下启用 **watch-it**。
### Codex
添加到 `~/.codex/config.toml`:
```toml
[mcp_servers.watch-it]
command = "/path/to/.venv/bin/python"
args = ["-m", "watch_mcp.server"]
```
或在一行中注册:
```bash
codex mcp add watch-it -- /path/to/.venv/bin/python -m watch_mcp.server
```
**示例用例:** 错误重现,实现演示中显示的 UI,从教程中提取步骤,从录制中生成 QA 重现步骤。
## 工作原理
```
watch(video_path, mode="sample")
→ 解析 + 缓存 本地文件(引用)或 yt-dlp 下载(复制);内容寻址 video_id
→ 场景检测 PySceneDetect 查找有意义的剪切点
→ 帧采样 每个场景一个关键帧(静态剪辑的间隔回退)
→ 缩放 Pillow,最长边约 768px
→ VLM 批处理帧 + 查询 → 严格的时间线 JSON
→ 验证 解析为类型化模型(一个修复重试错误的 JSON)
get_frames(video, end)
缓存查找 重解析的视频(不)
→ 抓 缩放 [start, end] 中均匀间隔的帧,作为图像返回
```
`mode="manual"` 在 缓存后停止 —LM — 以便代理可以通过 `get_frames` 完全驱动。
## 开发
```bash
pytest # 单元测试,以及在 ffmpeg 存在到端存根运行
python -m watch_mcp.server # 直接启动_stdio MCP 服务器
```
## 许可证
MIT — 请参阅 [`LICENSE`](LICENSE)。