
前言把一段视频丢给大模型让它帮你总结内容、回答画面里的问题听起来很美好。但你真去试就会撞上一堵墙把 YouTube 链接贴进 ChatGPT它读的是字幕文本根本没看画面。Claude 压根不接受视频文件。即便是原生支持视频的 Gemini默认也是按「每秒 1 帧」固定采样还得先把视频上传到谷歌云端快速切换的镜头很容易漏掉。换句话说大多数 AI 工具并不真正“看”视频。最近 GitHub 上一个叫claude-real-video缩写crv的开源项目给出了一个更聪明的本地方案它不按固定间隔截帧而是只在场景发生切换时才提取关键帧再用滑动窗口去掉近乎重复的画面最后用 Whisper 把音频转成文字——全部在你自己电脑上跑完数据不传云端。这篇文章就来拆解它到底聪明在哪、怎么用以及关键参数怎么调。背景或问题固定间隔采样为什么不行市面上很多“让大模型看视频”的脚本做法出奇地一致用 ffmpeg 按「每 N 秒一帧」把视频切成图片再一股脑塞给模型。这种固定间隔采样有三个硬伤。1. 静态内容被过度采样。一段 10 分钟的屏幕录制讲 PPT画面几乎不动按每秒 1 帧算就是约 600 张近乎一模一样的图。把这些全喂给模型除了烧 token、撑爆上下文窗口没有任何信息增量。2. 快速剪辑被采样不足。一段节奏很快的混剪两个关键镜头之间的切换可能只有 0.2 秒而你的采样间隔是 1 秒——恰好完美错过每一个镜头切换点模型拿到的全是“中间过渡帧”根本看不懂发生了什么。3. A-B-A 切回镜头被重复发送。视频里常见这种剪辑先给全景 A切到特写 B再切回全景 A。固定采样会把同一个全景 A 截下来重复发两遍模型被迫“看”两次已经看过的画面又浪费一轮上下文。把这三个问题叠加起来结果就是你喂给模型的帧很多但有效的很少上下文成本很高理解效果却很差。这正是 claude-real-video 要解决的矛盾。对比维度固定间隔采样claude-real-video帧选择每 N 秒一帧场景变化检测 密度下限重复镜头A-B-A 剪切每次都重复发送滑动窗口去重每个镜头只发一次静态幻灯片10 分钟约 600 张近乎相同的帧压缩为 1 帧去重快速切换剪辑漏掉采样间隔之间的帧捕捉每一次视觉变化音频通常被忽略字幕优先 Whisper 回退转录视频去向通常上传到云端留在你的机器上输入方式通常仅支持本地文件支持 URLyt-dlp或本地文件核心思路场景感知 去重 本地转录claude-real-video 的设计可以浓缩成一句话只把“画面真正发生变化”的关键帧喂给模型顺便把音频也变成模型能读的文字。它把整个流程拆成六步全部在本地完成获取Fetch用 yt-dlp 处理 URL支持 cookie 登录态或直接复制本地文件。提取Extract通过 ffmpeg 的时序选择通道捕获每一个场景切换点同时保证密度下限每--fps-floor秒至少一帧从而同时覆盖快速剪辑和慢速录屏。去重Dedup基于真实像素差异与最近保留的若干帧做滑动窗口比较丢掉重复镜头。文本Text如果视频自带字幕.srt/.vtt 或内嵌字幕轨道就直接用比重新转录更快更准没有字幕才回退到 Whisper。音频可选用--keep-audio保留完整原始音轨让支持听力的模型如 GPT-4o、Gemini能听到音乐和语调。清单文件Manifest生成MANIFEST.txt汇总所有信息供模型一次性读取。最终输出的是一个干净的本地文件夹关键帧图片 转录文本 清单。你把这个文件夹拖进任意大模型Claude / ChatGPT / Gemini就能基于画面提问了。实现步骤第一步安装 ffmpeg系统依赖claude-real-video 用 ffmpeg / ffprobe 做帧提取和音频处理但 ffmpeg 不能通过 pip 安装需要先单独装一次。操作系统命令macOSbrew install ffmpegLinuxsudo apt install ffmpeg或你的发行版包管理器Windowswinget install Gyan.FFmpeg或choco install ffmpeg并把bin\加入 PATH装完验证一下ffmpeg-version第二步安装 claude-real-video# 只装核心帧提取 去重pipinstallclaude-real-video# 想要音频转录加上 whisper 扩展pipinstallclaude-real-video[whisper][whisper]会顺带装上openai-whisper它同样依赖 ffmpeg。要求 Python 3.10 以上。第三步跑一个最简单的例子支持 YouTube、Instagram、TikTok 等链接也支持本地文件# 处理一个 YouTube 链接crvhttps://www.youtube.com/watch?vXXXXXXX# 处理本地文件指定输出目录和转录语言crv lecture.mp4-oout--langzh# 只提取帧不要转录crv clip.mp4 --no-transcribecrv是python -m claude_real_video的简写。跑完后输出目录长这样crv-out/ ├── frames/ │ ├── frame-001.jpg │ ├── frame-002.jpg │ └── ... ├── transcript.txt # 音频/字幕转录的纯文本 └── MANIFEST.txt # 清单帧列表 元信息把frames/整个文件夹加上MANIFEST.txt和transcript.txt一起拖进 Claude / ChatGPT / Gemini然后随便提问即可。代码示例命令行常用选项一览标志默认值含义-o, --outcrv-out输出目录--scene0.30场景切换敏感度值越低提取的帧越多--fps-floor1.0每 N 秒至少提取一帧密度下限--max-frames150总帧数的硬上限--langautoWhisper 语言en, zh, auto, …--dedup-threshold8像素变化比例超过才视为新帧值越高帧越少--dedup-window4与最近 N 个保留帧比较避免 A-B-A 重复--reportoff生成 report.html可视化每一帧的保留/丢弃决策--no-transcribeoff跳过音频转录--keep-audiooff同时保存完整音轨 audio.m4a--cookies–用于登录受限源的 Netscape cookie 文件Python API 调用如果你想在脚本或后端服务里集成直接调process函数fromclaude_real_videoimportprocess# 处理一个视频输出到 ./out转录语言设为中文rprocess(https://youtu.be/XXXXXXX,out,langzh,scene0.30,# 场景切换敏感度dedup_threshold8,# 像素变化阈值dedup_window4,# 滑动窗口大小)print(f提取的关键帧数量:{r.frame_count})print(f转录文本路径:{r.transcript_path})返回对象r包含帧数和转录文本路径方便你接着把图片和文本灌进自己的 RAG 或 Agent 流水线。一个完整的“视频问答”串联示例下面演示如何把 claude-real-video 的输出接入一个本地多模态问答流程伪代码示意思路importosfromclaude_real_videoimportprocess# 1. 本地处理视频得到关键帧 转录resultprocess(meeting.mp4,out,langzh,keep_audioFalse,# 不需要听音乐/语调可关掉max_frames60,# 控制上下文成本)frames_diros.path.join(out,frames)transcript_pathresult.transcript_path# 2. 读取转录文本withopen(transcript_path,r,encodingutf-8)asf:transcriptf.read()# 3. 把关键帧 转录交给多模态大模型以 OpenAI 兼容接口为例importbase64defencode_image(path):withopen(path,rb)asf:returnbase64.b64encode(f.read()).decode()frame_filessorted(os.path.join(frames_dir,f)forfinos.listdir(frames_dir)iff.endswith(.jpg))[:result.frame_count]# 构造多模态消息先给文字上下文再逐帧给图content[{type:text,text:f视频转录文本:\n{transcript}\n\n下面是关键帧请基于画面和文本回答问题。}]forfpinframe_files:content.append({type:image_url,image_url:{url:fdata:image/jpeg;base64,{encode_image(fp)}},})messages[{role:system,content:你是一个视频内容分析助手基于关键帧和转录回答用户问题。},{role:user,content:content},{role:user,content:请总结这段视频讲了什么重点在哪里},]# from openai import OpenAI# client OpenAI(api_key..., base_url...)# resp client.chat.completions.create(modelgpt-4o, messagesmessages, max_tokens800)# print(resp.choices[0].message.content)这个例子展示了 claude-real-video 在工程里的定位它是视频到多模态模型之间那座“聪明的桥”负责把原始视频压缩成模型能高效消化的关键帧 文字而真正理解和回答的活儿仍交给大模型。运行结果与效果说明用一个 10 分钟的技术演讲视频做对比测试能直观看出差异固定间隔采样每秒 1 帧约 600 帧其中 500 多帧是讲者站在同一张幻灯片前几乎不动模型上下文被无效图片占满回答时容易“Lost in the Middle”。claude-real-video默认参数通常压缩到 20~50 帧左右每一帧都对应一次真正的画面变化幻灯片切换、代码演示、图表出现外加一份转录文本。模型拿到的信息密度高、上下文成本低。如果你想直观看到它到底“丢掉了哪些帧、保留了哪些帧”加上--reportcrv lecture.mp4--report它会在dropped/目录里保存被丢弃的帧并生成一个report.html用可视化方式展示每一帧的保留/丢弃决策和差异百分比——这是调参时最实用的调试工具。深入关键参数怎么调理解了原理调参就有方向了。--scene场景切换敏感度默认 0.30这是 ffmpeg 场景检测的阈值。值越低越“敏感”稍微一点变化就判定为场景切换提取的帧越多值越高只有大幅度画面变化才被捕获帧越少。演讲/教学视频画面变化慢可适当调低到 0.20避免漏掉幻灯片切换。快速混剪/游戏录屏画面变化剧烈默认 0.30 通常够用太高会丢镜头。--dedup-threshold像素变化比例默认 8去重时两帧降采样后的像素差异比例超过这个值才认为是“新帧”。值越高过滤越狠帧越少。想保留更多细节调低到 4~6。想极致压缩上下文成本调高到 12~15。--dedup-window滑动窗口大小默认 4这是 claude-real-video 解决 A-B-A 切回镜头的关键。它不只和「前一帧」比而是和最近保留的 N 帧比。1只和前一帧比较遇到 A-B-A 会把第二个 A 当新帧重复发。4默认和最近 4 个保留帧比较镜头切回时认出“这个画面模型已经看过”直接丢弃避免重复发送。对于访谈、对话类视频频繁正反打镜头建议保持默认 4 甚至调高到 6对于线性教程画面单向推进调到 2 也够。为什么用降采样 RGB 而不是感知哈希pHash这是一个容易被忽略但很重要的设计选择。很多去重工具用感知哈希pHash / aHash但 claude-real-video 故意不用原因是感知哈希在纯色背景和等亮度的色相变化场景下会失效——两张颜色完全不同但亮度结构相似的图可能算出相同的哈希值被误判为重复。降采样 RGB 直接计算像素差异对纯色、色相变化更鲁棒误判更少。代价是计算量略大但因为已经降采样到很小尺寸这点开销可以忽略。常见问题与避坑1. 报错ffmpeg: command not foundffmpeg 没装或没加入 PATH。Whisper 也依赖 ffmpeg所以这是最常见的前置问题。装完用ffmpeg -version确认能调用。2. 处理 YouTube 链接失败 / 报 age-restricted / 地区限制yt-dlp 偶尔会因为网站策略变动失效先升级 yt-dlppip install -U yt-dlp。如果是登录受限内容你自己有权访问的用--cookies cookies.txt传入 Netscape 格式的 cookie 文件。注意切勿把 cookie 凭证提交到公开仓库。3. 转录文本为空或质量差claude-real-video 的策略是「字幕优先」如果视频自带 .srt/.vtt 或内嵌字幕轨道直接用比重新转录更快更准。只有没有字幕时才回退到 Whisper。如果转录为空检查视频是否真的有音轨无声轨会干净跳过不报错。--lang是否设对中文视频传zh不要让它 auto 错判。Whisper 模型大小长视频默认小模型可能漏字可考虑用更大模型需自行配置 whisper。4. 帧太多撑爆上下文窗口加--max-frames 60设置硬上限或调高--dedup-threshold和--scene来压缩帧数。原则喂给模型的帧不在多在于每帧都代表一次真正的视觉变化。5.--keep-audio和转录的区别--keep-audio保存的是完整原始音轨audio.m4a含音乐、音效、语调给支持听力的模型如 Gemini、GPT-4o实际“听”。而 transcript.txt 只有文字。两者互补文字任何模型都能读音频文件则让模型感知到情绪、节奏和音乐——对于音乐 MV、演讲语气分析很有用。6. 本地处理的隐私优势把视频上传云端处理如 Gemini 原生流程意味着你的视频内容离开本地。对于企业内部会议录像、含敏感信息的演示视频claude-real-video 的“全部本地”特性是一个硬需求关键帧、音轨、转录都留在你机器上不外传。总结让大模型“看”视频难点不在模型本身而在怎么把视频变成模型能高效消化的输入。固定间隔采样是最直觉的做法但也是最浪费的做法——它不分场景地轰炸上下文窗口真正有信息量的帧反而被稀释。claude-real-video 的核心价值就三句话场景感知提取只在画面真正变化时取帧静态内容不浪费、快速剪辑不漏帧。滑动窗口去重用真实像素差异对抗 A-B-A 重复每帧都算数。本地全流程字幕优先 Whisper 回退转录数据不出机器隐私可控。它不替代任何大模型而是做好“视频 → 关键帧 文字”这层脏活累活让 Claude、ChatGPT、Gemini 这些模型能把精力花在理解上而不是在海量重复帧里挣扎。如果你在做视频内容分析、会议纪要、教学视频问答这类场景值得一试。项目地址MIT 协议、Python 100%github.com/HUANGCHIHHUNGLeo/claude-real-video