内容
# 流卡
用于LLM代理的运动理解。 将视频压缩为 **一张带注释的可读图像** (“流卡”)和精确的机器可读统计数据,以便像Claude这样的图像强大/视频盲模型可以调试运动:游戏故障、渲染停顿、传送、z轴战斗闪烁、动画时序。
该方法纯粹是Eadweard Muybridge(1878年)的方法:将运动 collapse 到可以推理的静态图像中。
## 为什么
Claude没有原生的视频输入,即使是视频原生的LLM在运动方面也被证明是弱的——大多数在“向左或向右移动”方面得分接近随机(“方向运动盲”,[arXiv:2605.22823](https://arxiv.org/abs/2605.22823);另见[TempCompass](https://arxiv.org/abs/2403.00476))。流卡绕过了这个问题:确定性的CV将运动 *空间化*,代理用其强大的图像技能读取结果。工具中没有模型——免费、本地、可复制。
## 它生成什么
每个剪辑一张卡片。 编辑的电视剪辑——发现标志着镜头切换,时间线显示编辑节奏;胶片条固定每个镜头包含的内容:

单镜头夜间空中拍摄——没有剪切事件,时间线改为讲述相机故事:快速行进约5秒(洋红色凸起),然后缓慢滑动。注意视差警告:在3D相机行进下,路径/闪烁填充有风景片段,而相机统计数据和时间线保持可信:

## 工具(MCP)
注册一次(用户范围,每个项目可用):
```
claude mcp add --scope user flowcard -- D:\flowcard\venv\Scripts\python.exe D:\flowcard\server.py
```
- **`record(target, seconds, fps)`** — 捕获桌面(ddagrab/gdigrab)或单个窗口(`window:<exact title>`)并自动分析。返回`card_path`。
- **`analyze(video_path, t0, t1, roi, camera_comp)`** — 任意视频 → 流卡 + 统计数据。用`t0/t1`(秒)和`roi=[x,y,w,h]`进行深入分析。大于18秒的剪辑自动分段。
- **`compare(video_a, video_b)`** — 两个相同起始运行的视觉回归差异:分歧发生时间、最差区域边界框、A/B胶片条。
CLI等效项:
```
python -m flowcard clip.mp4 outdir [--t0 2] [--t1 8] [--roi x,y,w,h] [--no-camera-comp]
python tests\validate.py # 重新生成基准剪辑并检查所有内容
```
## 卡片
六个面板 + 时间线 + 胶片条,每个都标记并自我描述:
| 面板 | 它回答的问题 |
|---|---|
| 参考 | 场景是什么样的(中位数/稳定中位数) |
| 哪里 | 哪些像素发生变化,总运动能量 |
| 何时 | 每个像素的最后运动时间(蓝色=早 → 红色=晚) |
| 方向 | 平均光流方向(色调)+ 速度(亮度),移除相机 |
| 闪烁 | 每个像素变化的帧百分比 — 将闪烁/z轴战斗与运动分开 |
| 路径 | 跟踪的物体轨迹,按时间着色,带有出现标记 |
标题发现使用代理可以操作的固定词汇:`CAMERA`、`STALL`、`MICROSTUTTER`、`DISCONTINUITY`、`APPEARANCE`(传送/生成)、`FLICKER HOTSPOT`、`DOMINANT OBJECT MOTION`。`stats.json` 携带与数字相同的事实(所有坐标在 **frame-0 空间**;相机平移单独报告,每对系列包含在文件中,但从MCP响应中删除以保持上下文边界)。
## v2工作原理
1. **每帧对的相机估计**:LK特征轨迹 + RANSAC 部分仿射。移动物体是RANSAC异常值;背景获胜。
2. **稳定**:帧被扭曲到填充的画布上的frame-0坐标,因此每个面板在世界空间中显示 *物体* 运动;相机速度成为其自己的时间线曲线 + 统计数据。
3. **检测器** 在稳定堆栈上:运动能量、最后运动时间、DIS光流(Farneback备用)、占空比闪烁图 + 热点框、具有边缘片段凝聚的blob跟踪、空间新颖性出现检测(活动在≥0.2秒内无运动 = 传送/生成)、原始复制帧的停顿 + 微卡顿节奏。
## 验证
`tests\validate.py` 生成具有植入的基准真值的合成剪辑(渲染冻结、传送、闪烁补丁、弹跳 vs 线性移动、 正弦相机平移、+25像素回归错误)并断言每个事件都被恢复 — 21项检查,包括相机平移轨迹RMSE < 0.5像素/帧和比较()分歧发生时间在0.2秒内。截至v2,所有检查均通过。
## 它真的能帮助VLM吗?(基准测试)
`bench/run_bench.py` 在三个条件下运行qwen3-vl-32b-instruct(OpenRouter,pydantic-ai)两个未知的~11秒1080p剪辑 — 编辑的电视剪辑和单镜头夜间城市空中拍摄。原始输出在`bench/results/`中。定性,n=1每单元格:
| 条件 | 结果 |
|---|---|
| 原生视频上传 | **失败** — 在OpenAI兼容路径上不支持视频输入 |
| 8个均匀帧 | 良好的内容ID;找到约8个剪辑中的1个;错过两阶段相机配置文件;**发明技术** (“三脚架”,“无变焦”,根据其自己的采样间隔推断节奏,道具“在表演期间放置”) |
| 流卡 + 统计数据 + `grab_frames` 工具 | 每个标记的剪切都有确切的时间戳;单镜头从仪器正确确认;技术引用测量值(有效帧率、复制帧、相机百分比、平移/缩放);根据警告正确折扣视差轨迹 |
要点:
1. 卡片将VLM从 *描述采样图片* 转变为 *引用测量值* — 最大的增益在于事件结构(带有时间戳的剪切列表)和技术声明,帧基线在这些方面会产生幻觉。
2. 基线的失败模式正是该工具针对的:它从自己的采样网格进行推理(“节奏慢”,“相机静态”),因为它从未看到帧之间。
3. 诚实的错失:均匀采样捕获了一个屏幕上的名片,而事件驱动的帧抓取跳过了 — 因此推荐的配方(现在在`bench/card_system_prompt.md`中)是卡片 + 事件帧 + 均匀分布。仪器和全面覆盖是互补的,而不是替代品。
## 已知限制
- 稳定重采样在相机运动下在WHERE中留下了微弱的背景回声(对象仍然占主导地位;统计数据不受影响)。
- 可检测的运动受捕获帧率的限制;以≥应用程序的帧率记录。
- 全屏场景剪切被读取为全局不连续性,而不是对象事件。
- 相机模型是部分仿射的(平移/旋转/缩放)— 强的视差或FPS相机旋转在3D世界中违反它;面板逐渐退化,但世界坐标变得近似。
## 路线图(v3)
- RAFT光流 + CoTracker点轨迹(torch,GTX 1080)用于小/快物体保真度
- SAM2物体掩模 → 每物体运动卡片
- HUD OCR,用于将运动事件与屏幕状态关联
- 比较()的时序对齐(DTW),适用于不同步启动的运行