OpenMontage video-understand 技能指南:本地化视频内容理解,零 API 密钥的帧抽取与转写方案
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
视频内容理解是智能视频生产流水线中"看片"的起点:无论是审片、素材分析还是质量把关,都需要先把视频"翻译"成模型可读的结构化数据。OpenMontage 仓库内置的video-understand技能(.claude/skills/video-understand/SKILL.md)提供了一套完全本地化、无需任何 API 密钥的视频理解方案:用 ffmpeg 完成场景检测与关键帧抽取,用 Whisper 完成本地语音转写,最后输出一份结构化的 JSON 报告,供下游 Agent 继续做视觉分析、质量门禁或剪辑决策。读完本文,你将掌握该技能的全部 CLI 参数、三种帧抽取模式的原理与适用场景、JSON 输出 schema 的每个字段,以及它在 OpenMontage 工具生态(如video_understand工具、审片与质量门禁流程)中的实际用法。
技能定位:为什么需要"本地视频理解"
视频内容理解在 OpenMontage 的生产流水线中承担三类职责:看懂素材(用户提供的素材里有什么)、验证产出(生成的镜头是否符合预期)、质量把关(渲染结果是否清晰、曝光是否正确)。
其核心痛点在于:直接调用云端多模态模型来分析视频,往往面临成本高、延迟大、隐私与密钥管理的三重问题。video-understand技能给出的答案是"本地优先":
- ffmpeg + ffprobe(必需)负责视频元数据探测与帧抽取,完全离线;
- openai-whisper(可选)负责本地语音转写,同样不需要联网;
- 整条链路不需要申请、配置或传递任何 API 密钥,这正是该技能在 SKILL.md 开头反复强调的 "No API keys needed" 的落点。
从仓库的技能索引(skills/INDEX.md)可以看到,video-understand被登记为"Video Understanding"能力,用于"Visual QA, quality gating, scene classification",与之配套的用法说明见skills/creative/video-understand-usage.md。也就是说,这条技能是 OpenMontage 面向 Agent 的"视频眼睛"——负责把连续的视频流沉淀为离散、可检索的帧与文字证据。
前置依赖与环境准备
按 SKILL.md 的 Prerequisites 章节,依赖分两级:
# 必需:ffmpeg + ffprobe(帧抽取与元数据探测) brew install ffmpeg # 可选:Whisper(语音转写,若不安装则仅输出帧) pip install openai-whisper值得补充的是脚本对依赖的运行时检查逻辑。查看入口脚本.claude/skills/video-understand/scripts/understand_video.py:
main()在启动时会用shutil.which()分别校验ffmpeg与ffprobe,缺失任何一个都会直接报错退出,避免在中途产生难以排查的半成品结果;- Whisper 的缺失不会阻断流程:脚本会打印
Warning: Whisper is not installed. Skipping transcription.并继续完成帧抽取,最终 JSON 中transcript与text两个字段为null; - 在交互式终端(
stderr是 TTY)下,脚本还会主动询问是否自动pip install openai-whisper,非交互环境则静默跳过(见_check_and_offer_install())。
这种"必需项硬校验、可选项软降级"的设计,保证了脚本在只有 ffmpeg 的极简环境里也能产出有价值的帧数据。
CLI 使用手册:从默认命令到完整参数
常用命令一览
SKILL.md 给出了可直接复制的命令族(以下均相对仓库根目录执行):
# 默认:场景检测 + 语音转写 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 # 关键帧(I 帧)抽取 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 -m keyframe # 等间隔抽帧 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 -m interval # 限制抽取帧数 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 --max-frames 10 # 换用更大的 Whisper 模型 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 --whisper-model small # 只抽帧、跳过转写 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 --no-transcribe # 静默模式:只输出 JSON,不带进度日志 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 -q # 结果写入文件而非 stdout python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 -o result.json注意:脚本内部的 docstring 与 argparse 示例中保留了
skills/video-understand/scripts/understand_video.py的写法;由于当前仓库中该技能位于.claude/skills/video-understand/目录下,请以本文给出的.claude/skills/video-understand/scripts/understand_video.py路径为准。
完整 CLI 参数表
| Flag | 类型/取值 | 说明 |
|---|---|---|
video | 位置参数,必填 | 输入视频文件路径 |
-m, --mode | scene(默认)/keyframe/interval | 帧抽取模式 |
--max-frames | 整数,默认20 | 最多保留的帧数 |
--whisper-model | tiny/base(默认)/small/medium/large | Whisper 模型尺寸 |
--no-transcribe | 布尔开关 | 跳过语音转写,只抽帧 |
-o, --output | 文件路径 | 将结果 JSON 写入文件而不是 stdout |
-q, --quiet | 布尔开关 | 抑制进度信息,仅输出 JSON |
这些参数在 build_parser() 中均有对应实现,其中--mode与--whisper-model通过choices白名单约束非法取值,--max-frames的默认值来自模块常量_DEFAULT_MAX_FRAMES = 20。
边界行为:YouTube URL 与文件校验
脚本对输入做了两道防线(见main()):
- YouTube URL 拦截:当输入路径包含
youtube.com/、youtu.be/、youtube-nocookie.com/时,脚本会明确报错并提示先用仓库的video-download技能下载视频再分析,而不是试图直接解析在线视频; - 本地文件校验:
os.path.isfile()检查输入是否存在,不存在则报video file not found并退出。
这意味着该脚本只面向本地文件,在线素材需要先走下载链路(对应技能skills/creative/video-download.md所描述的能力)。
三种帧抽取模式:原理、命令与适用场景
| 模式 | 工作原理 | 最适用场景 |
|---|---|---|
scene(默认) | 通过 ffmpeg 滤镜select='gt(scene,0.3)'检测画面切换点 | 大多数视频、内容变化明显的素材 |
keyframe | 抽取编码层的 I 帧(关键帧) | 具有天然关键帧布局的已编码视频 |
interval | 依据时长与 max-frames 等间隔抽样 | 固定采样、输出可预期的场景 |
三种模式在源码中分别对应 extract_frames_scene()、extract_frames_keyframe() 与 extract_frames_interval()。
scene 模式的实现细节:使用select='gt(scene,0.3)'滤镜(场景变化阈值 0.3,对应常量_SCENE_THRESHOLD),配合showinfo滤镜把每个选中帧的pts_time打印到 stderr,再由_parse_showinfo_timestamps()用正则pts_time:\s*([\d.]+)解析出精确时间戳,最后以-vsync vfr+-q:v 2输出高质量 JPEG。
关键行为:场景模式的自动回退。如果scene模式未检测到任何场景切换,understand_video() 会自动回退到interval模式重新抽取,并在最终 JSON 的mode字段中如实反映实际使用的模式(例如输出"mode": "interval")。这一点在 output-format.md 的 "Null Fields" 一节中也有明确说明,读者在解析结果时不要假设mode一定等于请求值。
帧数约束机制:无论哪种模式先抽出了多少帧,subsample_frames()都会把结果收敛到--max-frames以内,且策略是"保留首帧与末帧,中间均匀采样"(首尾各占一个名额,其余帧在中间等距取点并去重)。这种设计保证了 Agent 在有限上下文中总能拿到覆盖视频头尾的概览帧。interval模式的步长计算为max(duration / max_frames, 0.1),即最短 0.1 秒抽一帧,避免对超短视频产生无意义的密集输出。
JSON 输出格式:完整 Schema 与字段语义
脚本默认把结果 JSON 输出到 stdout(-q可去掉进度日志),或用-o写入文件。完整 schema 见.claude/skills/video-understand/references/output-format.md,示例输出:
{ "video": "video.mp4", "duration": 18.076, "resolution": {"width": 1224, "height": 1080}, "mode": "scene", "frames": [ {"path": "/abs/path/frame_0001.jpg", "timestamp": 0.0, "timestamp_formatted": "00:00"} ], "frame_count": 12, "transcript": [ {"start": 0.0, "end": 2.5, "text": "Hello and welcome..."} ], "text": "Full transcript...", "note": "Use the Read tool to view frame images for visual understanding." }顶层字段
| 字段 | 类型 | 说明 |
|---|---|---|
video | string | 输入视频文件名(basename) |
duration | float | 视频时长(秒) |
resolution | object | 分辨率,含width/height |
mode | string | 实际使用的抽取模式:scene/keyframe/interval |
frames | array | 抽取出的帧对象数组 |
frame_count | integer | 帧数量 |
transcript | array 或 null | 转写分段数组;跳过转写或 Whisper 缺失时为null |
text | string 或 null | 全文转写字符串;同上为null |
note | string | 给下游 Agent 的使用提示(用 Read 工具查看帧图) |
帧对象(frames 数组元素)
| 字段 | 类型 | 说明 |
|---|---|---|
path | string | 帧 JPEG 的绝对路径 |
timestamp | float | 相对视频起点的帧时间(秒) |
timestamp_formatted | string | 人类可读时间戳,MM:SS或HH:MM:SS格式 |
转写分段(transcript 数组元素)
| 字段 | 类型 | 说明 |
|---|---|---|
start | float | 分段起始时间(秒) |
end | float | 分段结束时间(秒) |
text | string | 该分段转写文本 |
帧文件的落盘约定
帧图片输出在视频文件同目录下的{视频文件名去掉扩展名}_frames/文件夹中:
video.mp4 video_frames/ frame_0001.jpg frame_0002.jpg ...目录名规则即{video_stem}_frames(见understand_video()中frames_dir = os.path.join(video_dir, f"{video_stem}_frames"))。JSON 中的帧路径一律是绝对路径,设计意图是让下游 Agent 可以直接用 Read 工具读取图片做视觉理解。
转写链路与时间戳补偿
转写部分值得展开的源码细节有两处:
- 音频预处理:
extract_audio()先用 ffmpeg 把音轨抽取为16 kHz、单声道、pcm_s16le的 WAV(-ar 16000 -ac 1),这是 Whisper 的标准输入规格;若视频无音轨或抽取为空,会打印警告并跳过,不会让整个流程失败。 - 双通道 Whisper 调用:
transcribe_with_whisper()优先尝试 Python 包方式import whisper并load_model();若导入失败,再回退到whisperCLI(--output_format json)并把结果写进临时目录解析,最后清理临时文件。两种路径都会把分段时间戳round(..., 3)保留三位小数。 - 帧时间戳补偿:
assign_timestamps()负责兜底——若某帧没有解析到时间戳(keyframe 模式即属此类),则按时长均匀估算补齐;_format_timestamp()则在超过一小时时自动从MM:SS切换为HH:MM:SS。
在 OpenMontage 工具生态中的定位与典型工作流
video-understand技能与仓库工具video_understand(对应tools/analysis/video_understand.py)在能力上互补:前者负责"本地抽帧 + 转写"产出证据,后者负责"对帧做模型级视觉理解"(describe / qa / quality / classify 等模式)。配套用法文档skills/creative/video-understand-usage.md给出了几条可直接落地的典型流程:
- 剪辑前素材审查:
video_understand (describe, 10 frames) → inform scene_plan。先用本地抽帧+转写快速掌握用户素材内容,再进入分镜规划; - 渲染后质量门禁:
video_understand (quality) → pass/fail → re-render if needed。质量模式按blur_score < 100、亮度不在 50–200、contrast < 30判定不合格,建议至少采样首、中、尾三帧; - 高光片段挑选:
video_understand (describe, 20 frames) → rank by visual interest → select clips,为预告片或蒙太奇筛选视觉上最有吸引力的段落; - 资产生成验证:
video_understand (qa, "Does this match: [scene description]?") → confirm or regenerate,确认生成的图像/片段与场景描述一致再进入下一步; - 口播人像分析:
video_understand (qa, "Is the speaker's face clearly visible?") → face_enhance if needed,在唇形同步或人脸修复前先确认面部可见性。
这些工作流强调一个共同原则——"战略性采样,而非穷举":不要在长视频上对每一帧都跑视觉理解,而是先用本技能的scene/interval模式把帧数收敛到--max-frames(默认 20)以内,再交给视觉模型做精细分析。这与 output-format.md 中 "Claude can view JPEG images directly ... without any cloud APIs" 的定位一致:帧图 + 转写文本组合,就是一套无需云端 API 的完整视频理解证据链。
小结
video-understand技能用两个成熟的开源组件(ffmpeg 与 Whisper)解决了视频理解的第一公里问题:
- 抽帧:三种模式(场景检测、关键帧、等间隔)各有侧重,
scene模式在无场景切换时自动回退interval,保证任何输入都有产出; - 转写:自动探测 Python 包或 CLI 两种 Whisper 形态,音轨预处理与时间戳兜底逻辑完整,缺 Whisper 时优雅降级;
- 输出:结构化 JSON 携带元数据、绝对路径帧表与时间戳分段,
-o落盘与-q静默模式适配脚本化与 Agent 化两种调用场景; - 生态衔接:与
video_understand工具的 describe / qa / quality 模式配合,形成"本地证据采集 → 模型级视觉理解 → 质量门禁/审片决策"的完整链路。
对任何想在自己的 Agent 工作流里加入"看懂视频"能力的开发者而言,这条技能的最大价值是:零密钥、零云端依赖、输出即插即用的结构化 JSON,从环境就绪到拿到首份视频报告,只需要 ffmpeg 与一条命令。
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考