帧选择就是一切:让LLM看视频的笔记
摘要
面向LLM视频输入的帧选择优化工程笔记,涵盖场景检测、去重策略以及token预算管理。
暂无内容
查看缓存全文
缓存时间: 2026/08/04 01:36
# 帧选择就是全部:让LLM看视频的工程笔记
Source: https://leoaido.com/how-llms-watch-video
## 视频不是关于视频的文章
当同样内容的文字稿所花的 token 要少得多时,为什么还要把视频喂给模型?
因为文章是某人对事件的压缩。一个人看了事件,决定哪些重要,把其余扔掉。那些取景、时机、屏幕上他们认为不相关的东西。当 LLM 读到文章时,它学到的是那位作者的选择。它无法恢复被剪掉的内容,也无法对从未见过的取舍提出异议。
把视频交给模型,压缩步骤就转移到了模型身上。它看到演示实际的样子,而不是评测者所说的样子。它注意到教程中一闪而过、没人费心转写的错误信息。它看出“快速设置”其实剪了十一次。同一主题,完全不同的立场:阅读证人陈述 vs 成为证人。这就是为什么 token 成本值得付出,也是本文余下部分要讨论如何用好这些 token 的原因。
## 预算问题
如今大多数“视频理解”就是一份转录文本加上按时间抽样的帧。每秒一帧,或者每十秒一帧。均匀抽样同时朝两个方向失效:它让模型淹没在一堆几乎相同的说话人头像帧中,又恰好跳过了真正发生了事情的那一秒。两次失效的根源相同:抽样器不知道什么发生了变化。
决定一切的约束是 token 预算。图像是你能放进上下文窗口中最昂贵的东西。一旦你接受“每段视频大约 100 到 150 帧,就这样”,提取就不再是问题。选择才是问题。每一帧保留下来的帧都必须为自己赢得位置。
## 场景检测,以及为什么固定阈值不够用
第一步是标准做法:使用 ffmpeg 的 `scene` 分数。在每次场景变化处取一帧,再加上一个低密度兜底,这样长镜头不剪切也至少能产出一些帧。整个过程按时间顺序单次完成,因为后面的去重要比较真正的相邻帧。
固定阈值在特定类型的内容上会失效:动画和缓慢的镜头运动。卡通角色压扁拉伸,或者慢速摇摄,画面一直在变,但从未剧烈变化。分数永远越不过阈值线,抽样器就把整个过程睡过去了。解决办法很无聊但有效:在仅计算元数据的遍历中计算每帧的场景分数,然后当某帧的分数超过*滚动平均*的若干倍时,就保留该帧。高动态素材会抬高自己的门槛,安静素材会降低门槛。无需任何人调参。
## 去重:一个通道变成了三个
去重一开始只有一个比较器,每当真实视频让它难堪,它就多长出一个通道。
### 1. 全局通道
降采样到 16×16 的 RGB 签名,统计任一通道中变化超过 25/255 的单元格,如果变化少于约 8% 就丢弃该帧。用 RGB 而不是灰度,因为在灰度比较器看来,亮度相等的红到绿切换看起来一模一样。而且要跟最近四个*已保留*帧的滑动窗口做比较,而不仅仅是前一个。否则 A-B-A 剪辑(采访镜头、反应镜头、再回到采访)会因为中间隔了另一帧,就把模型已经看过的镜头重新收进来。
### 2. 动作通道
百分比阈值对小型主体存在结构性失明。一个人只占全景画面的 0.5%,无论做什么都不可能改变 8% 的像素,于是重要的那一秒就被去重掉了。这不是我在基准测试里发现的,而是一位用户在工具跑了 2,181 个真实视频后发现的。修补办法:在 32×32 的网格上,哪怕只有少数几个单元格发生*剧烈*变化(超过 45/255),无论百分比多少,该帧都算新帧。小主体、剧烈变化,保留。
### 3. 稳定通道
全局通道也看不到小的*局部*状态变化:字幕切换、白板上出现一条笔迹、UI 元素更新。这些在 16×16 下测出来是 0.0%。所以第三个通道在 192×192 的签名上工作,寻找与已保留窗口中的*每一*帧都强烈不同的像素。匹配时允许正负 1 像素的偏移,否则胶片晃动、传感器抖动和噪点会到处显示为变化。
在这里,保护措施比检测器更重要。它只在场景其余部分静止时运行,因为运动是另外两个通道的活。候选像素还要经过第二轮更严格的容差检查。这能干掉烟雾消散这类柔和对比度的漂移,而笔迹和文字保持硬核,顺利活下来。另外,每次触发保留都会抬高门槛,并带有一个衰减冷却期,所以一面每秒都在“稳定下来”的旗帜不可能每次都被抓帧,而单独一张新文字卡片可以在基础门槛通过。没有冷却期,这一个通道就会在挥舞的旗帜上吃掉整份帧预算。
## 将帧与转录文本融合
文本来源:如果视频自带嵌入字幕,就用字幕;否则使用本地 Whisper。有两个细节花了不少调试时间:
- Whisper 在纯音乐音频上有时会幻觉出一段*远远超出视频结束*的文字。如果构建时间线时完全相信片段时间戳,幽灵行就会被照单全收。所以所有内容都被钳制到媒体时长,再加一秒容差,因为时长在上游经常被截断成整数。
- 把转录文本和一堆帧交给模型,让它“按时间戳”自己去连接,在短视频上没问题,但在长视频上会悄悄错位。某帧被引用到错误的句子上。所以连接是预计算好的:每个转录片段列出落在其中的帧,超过 1.5 秒的静音变成仅含帧的时间段。一个时钟。不需要读者再自行拼接。
所有产物都是普通文件:JPEG 图像、一份文本转录、一个告诉模型如何解读整个包的清单。输出故意做得很朴素。这正是它能跨模型移植的原因。
## 通过 MCP 提供服务
最新的接口是 MCP 服务器:`pip install "claude-real-video[mcp]"`,然后运行 `crv-mcp`。任何 MCP 客户端(Claude Desktop、Claude Code、Cursor)都可以对 URL 或文件调用 `watch_video`,拿回融合后的结果。两个预算决策被直接继承过来。帧在以内联方式返回前会先缩放到长边 768px,因为全分辨率帧只会烧掉上下文,对视觉毫无增益。分析按来源缓存,所以针对同一视频的后续问题永远不会重新下载或重新提取任何内容。
## 试试看
上面所有功能都包含在这个免费、MIT 许可的工具中。一条命令进去,普通文件出来:
``
# 需要 Python 3.10+ 和 ffmpeg
pip install "claude-real-video[whisper]"
crv "https://youtube.com/watch?v=..." # 或本地文件
→ frames/*.jpg # 选出的关键帧
→ transcript.txt # 带时间戳,并与帧融合
→ MANIFEST.txt # 告诉任何LLM如何读取这个包
``
把输出拖进任何具备视觉能力的模型,或者让 MCP 客户端通过 `crv-mcp` 自己驱动整个流水线。
## 这仍然捕捉不到什么
关键帧和融合转录文本能告诉模型屏幕上有什么、说了什么。它们不携带镜头如何运动、剪辑节奏、或声音的语气。那是另一个感知问题,不在本文范围内。但对于“让模型在回答之前真正看一遍这个东西”的日常场景,选帧加融合能覆盖相当大的地盘,而且完全在你自己的机器上完成。
代码,包括上述所有功能:[github.com/HUANGCHIHHUNGLeo/claude-real-video](https://github.com/HUANGCHIHHUNGLeo/claude-real-video)(MIT)。
相似文章
LiteFrame 扩展视频大语言模型效率(6分钟阅读)
LiteFrame 为视频大语言模型引入了一种高效的视频编码器,采用压缩令牌蒸馏技术,在保持准确率的同时,能够处理多达8倍的帧数并降低35%的延迟,为长视频理解开创了新的帕累托前沿。
LiteFrame: 高效视觉编码器解锁视频大语言模型的帧缩放
LiteFrame提出了一种轻量级视频编码器,采用压缩令牌蒸馏(Compressed Token Distillation)训练,可降低延迟,并使视频大语言模型能够处理8倍以上的帧数以实现长视频理解,在降低计算量的同时提高准确性。
选择、压缩、再投资:长视频多模态语言模型中视觉令牌分配的控制性研究
本文对长视频多模态语言模型的视觉令牌分配进行了控制性研究,发现帧选择显著提升准确性,而空间压缩在节省的令牌重新投资到更多帧时几乎是免费的,强调了统一比较框架的必要性。
面向高效全模态LLM的阶段自适应Token选择方法
SEATS是一种无需训练的阶段自适应Token选择方法,通过逐步剪枝冗余的视觉和音频Token来降低全模态LLM的计算开销,实现了9.3倍FLOPs减少和4.8倍预填充加速,同时保持96.3%的性能。
为什么视频处理仍然如此昂贵?视频和视听大语言模型推理效率机制综述
本综述研究了视频大语言模型的推理效率技术,分析了在帧采样、编码、令牌压缩和语言模型阶段的成本降低,同时识别了评估缺口。