OpenMontage video-understand 技能输出格式详解从 JSON 结构到帧与转写数据的消费【免费下载链接】OpenMontageWorlds 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技能的官方输出格式文档output-format.md展开完整拆解understand_video.py脚本产出的 Result JSON 的全部字段、取值约束与边界语义并追溯其背后的实现understand_video.py。读完本文你将掌握如何解析该 JSON 中的视频元数据、帧列表与 Whisper 转写结果理解scene/keyframe/interval三种提取模式对输出字段的影响以及如何将帧路径与转写文本直接交给 LLM 实现完全离线、无需任何云 API 的视频内容理解。Result JSON一次运行的全部产物主脚本understand_video.py将分析结果以 JSON 对象的形式输出到标准输出stdout或通过-o参数写入文件。该 JSON 同时承载三类信息视频元数据、抽取帧路径、转写数据。完整示例来自 output-format.md{ video: video.mp4, duration: 18.076, resolution: { width: 1224, height: 1080 }, mode: scene, frames: [ { path: /absolute/path/to/frames/frame_0001.jpg, timestamp: 0.0, timestamp_formatted: 00:00 }, { path: /absolute/path/to/frames/frame_0002.jpg, timestamp: 3.2, timestamp_formatted: 00:03 } ], frame_count: 12, transcript: [ { start: 0.0, end: 2.5, text: Hello and welcome to this video. }, { start: 2.8, end: 5.1, text: Today we will discuss... } ], text: Hello and welcome to this video. Today we will discuss..., note: Use the Read tool to view frame images for visual understanding. }从源码看该对象由understand_video()函数在 understand_video.py 中统一构造duration精确到毫秒round(duration, 3)transcript字段按时间顺序排列text是全部转写文本的拼接结果。顶层字段Top-Level Fields原文档给出的字段语义如下字段类型说明videostring原始视频文件名basenamedurationfloat视频时长秒resolutionobject视频分辨率含width与heightmodestring实际使用的提取模式scene、keyframe或intervalframesarray抽取帧对象数组frame_countinteger抽取的帧数transcriptarray 或 null转写分段数组跳过转写时为nulltextstring 或 null完整转写的单一字符串跳过时为nullnotestring提示 Claude 如何使用帧图像的说明字段背后的实现细节video在 understand_video.py 中通过os.path.basename(video_abs)取文件名不含目录路径便于在日志与报告中直接展示。duration与resolution来自 ffprobe 探测。probe_video()使用ffprobe -print_format json -show_format -show_streams读取视频流取首个codec_type video流的宽高以及format.duration作为时长understand_video()输出时对时长执行round(..., 3)保留三位小数。mode记录的是实际生效的提取模式。这一点在“Null 字段与回退语义”一节还会展开——当scene模式未检测到任何场景变化时脚本自动回退到interval模式且mode字段会如实反映回退后的结果。note固定为Use the Read tool to view frame images for visual understanding.是面向 Claude 等 LLM 代理的操作提示引导其对frames[].path执行视觉读取。帧对象Frame Objectframes数组中的每个元素描述一张已抽取的 JPEG 帧字段类型说明pathstring抽取到的 JPEG 帧的绝对路径timestampfloat帧在视频中的时间戳距片头的秒数timestamp_formattedstring人类可读时间戳格式为MM:SS或HH:MM:SS两个字段值得深入说明timestamp的精度源码中统一为round(ts, 3)。三种提取模式获得时间戳的方式不同scene模式解析 ffmpegshowinfo过滤器输出的pts_timeinterval模式按i * interval计算keyframe模式无法直接从过滤器得到时间戳会在后续的assign_timestamps()阶段按时长均匀估算补齐。timestamp_formatted的规则_format_timestamp()实现为——视频时长超过 1 小时输出HH:MM:SS否则输出MM:SS且对负值做max(0.0, seconds)保护。转写分段Transcript Segmenttranscript数组中的每个元素对应一段 Whisper 转写结果字段类型说明startfloat分段起始时间秒endfloat分段结束时间秒textstring该分段的转写文本Whisper 原生输出即带segments列表脚本将其中的start、end各做round(..., 3)处理并strip()文本保持与timestamp一致的毫秒级精度。text字段则是 Whisper 结果中result[text]的拼接版二者配合可同时满足“逐句对齐”与“全文检索”两种消费方式。帧路径约定Frame Path Convention帧被抽取到视频文件旁的同名目录中目录名为{视频主文件名}_framesvideo.mp4 video_frames/ frame_0001.jpg frame_0002.jpg ...对应实现位于 understand_video.py 的understand_video()主流程video_abs os.path.abspath(video_path) video_dir os.path.dirname(video_abs) video_stem os.path.splitext(os.path.basename(video_abs))[0] frames_dir os.path.join(video_dir, f{video_stem}_frames) os.makedirs(frames_dir, exist_okTrue)JSON 中的frames[].path均为绝对路径os.path.abspath可直接用于 Read 工具无需再做路径拼接frames_dir的exist_okTrue也保证了重复运行时不会因目录已存在而中断。Null 字段与回退语义原文档明确了两个关键的“非正常路径”行为transcript与text为null当使用--no-transcribe跳过转写或本机未安装 Whisper 时二者不再包含数据。scene模式自动回退若场景检测未找到任何场景变化模式自动回退为interval且mode字段反映实际使用的模式。结合源码可以给出更精确的边界说明在 understand_video.py 中当mode scene且extract_frames_scene()未产出任何帧时会打印No scene changes detected, falling back to interval mode日志并改用extract_frames_interval()随后actual_mode interval被写入结果的mode字段。转写链路本身具备三级降级先尝试 Python 包import whisper失败则尝试whisperCLIshutil.which两者都不可用时输出安装提示并跳过。若视频无音轨extract_audio()也会返回None并跳过转写。需要留意的一处文档与实现差异output-format.md约定未转写时transcript/text为null而从当前源码结构看understand_video()对这两个字段的初始值是空列表[]与空字符串仅在转写成功时填充。对于消费端而言null与空集合/空字符串均表示“无转写数据”两者可等价处理若你的解析逻辑依赖null判断建议同时兼容这两种取值。与 Claude 配合使用Using with Claudeframes数组返回的路径是绝对路径意味着下游工具可以零成本地读取这些 JPEG 帧用 Read 工具逐个读取frames[].path指向的 JPEG 图像Claude 直接查看图像并描述画面内容将画面描述与transcript/text结合即可获得完整的视频语义。整个过程完全本地化——帧抽取依赖 ffmpeg转写依赖本地 Whisper不涉及任何云 API。这一设计在 SKILL.md 中被明确为技能的核心卖点No API keys needed。仓库中 video-understand-usage.md 进一步给出了典型消费场景例如后期渲染的质量门禁quality检查模糊/过曝/低对比度、talking-head 管线开头的素材分析以及生成资产的视觉验证QA 模式核对画面与场景描述是否一致。命令行实操如何产出并消费这份 JSONunderstand_video.py的完整用法定义在 SKILL.md 中。注意脚本实际位于.claude/skills/video-understand/scripts/目录在技能已装载的 Claude Code 会话中可直接以技能形式调用# 场景检测 转写默认输出 JSON 到 stdout python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 # 关键帧提取 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 # 结果写入文件 python3 .claude/skills/video-understand/scripts/understand_video.py video.mp4 -o result.jsonCLI 选项速查参数说明video输入视频文件位置参数必填-m, --mode提取模式scene默认、keyframe、interval--max-frames最多保留的帧数默认 20--whisper-modelWhisper 模型规格tiny、base、small、medium、large默认 base--no-transcribe跳过音频转写仅抽帧-o, --output将结果 JSON 写入文件而非 stdout-q, --quiet抑制进度信息仅输出 JSON影响 JSON 输出的前置校验入口main()在进入管线前会执行三组校验任一失败都会直接退出因此能输出 JSON 即代表输入合法YouTube URL 拦截路径命中youtube.com/、youtu.be/、youtube-nocookie.com/时直接报错提示先使用下载技能获取本地文件_is_youtube_url()_YOUTUBE_PATTERNS。文件存在性os.path.isfile()校验输入视频真实存在。外部依赖ffmpeg与ffprobe必须都存在于 PATH否则提示先安装 FFmpeg。三种提取模式如何塑造frames与modemode字段的取值直接决定了frames数组的构成方式三个分支在understand_video()中对应三个独立函数模式实现方式帧的分布时间戳来源适用场景sceneffmpegselectgt(scene,0.3)showinfo集中在画面突变点解析showinfo输出的pts_time内容多样的大多数视频keyframeffmpegselecteq(pict_type,I)编码关键帧I 帧位置无直接来源后续按时长估算关键帧分布自然的编码视频intervalffmpegfps1/interval按时长均匀分布i * interval固定采样、输出可预期三个分支之后都会经过subsample_frames()与assign_timestamps()两道公共处理前者在帧数超过max_frames时保留首尾帧、中间均匀采样max_frames为 1 或 2 时分别退化为单帧与首尾两帧后者保证每个帧都有时间戳——缺时间戳时按时长均匀分配部分缺失时在已有时间戳之后按剩余时长等距补足。阈值常量同样集中在脚本头部场景阈值_SCENE_THRESHOLD 0.3默认帧数_DEFAULT_MAX_FRAMES 20默认 Whisper 模型_DEFAULT_WHISPER_MODEL base。仓库内的关联实现与验证围绕该输出格式仓库中还提供了两处可交叉印证的实现技能脚本本体.claude/skills/video-understand/scripts/understand_video.py 即本文所有字段的产出方技能入口 SKILL.md 定义了命令与参数references/output-format.md即本文依据定义了 schema。工具层实现tools/analysis/video_understand.py 中的VideoUnderstand工具走的是另一条技术路线CLIP/BLIP-2/LLaVA 视觉语言模型逐帧分析其agent_skills [video-understand]声明了与技能的同源关系但输出 schema 不同frames/summary/mode/model。从源码结构看技能脚本面向“抽帧 转写 供 LLM 看图”的离线流程而工具面向本地 VLM 推理的自动分析二者互为补充。采样正确性测试tests/tools/test_video_understand_sampling.py 通过伪造 ffmpeg 调用断言了帧采样的关键性质-ss落点必须贯穿整段视频如 100 秒视频、4 帧的落点为 12.5 / 37.5 / 62.5 / 87.5显式frame_indices必须走select过滤器时长未知时必须回退到均匀抽取——这些性质保证了frames[].timestamp对整段视频的代表性进而保证“看图理解”不会因采样集中在片头而失真。小结video-understand技能的输出格式是一条设计干净的契约video/duration/resolution提供元数据frames携带可直接读取的绝对路径 JPEG 帧与秒级时间戳transcript/text提供与帧对齐的语音内容mode忠实记录实际生效的提取策略。理解这份契约后无论是人工用 Read 工具看图、用解析脚本消费 JSON还是让 Agent 组合画面描述与转写文本都能在一个完全本地、无 API Key 的环境中完成对任意视频的结构化理解。【免费下载链接】OpenMontageWorlds 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),仅供参考
