基于 ffmpeg 与 Skill 机制:为 Agent 构建视频理解能力
1. 为什么我要给 Agent 装上一双“眼睛”
做 Agent 开发的朋友大概都有过这种体验:你精心搭好了一套工作流,让模型去处理一批素材,结果卡在第一步——它看不见视频里到底有什么。文本、图片、PDF 这些早就被各种工具啃得透透的,唯独视频这块,一直是个尴尬的盲区。你丢一个 mp4 过去,模型要么直接拒收,要么只能靠文件名瞎猜。claude-video 这个 Skill 要解决的就是这件事:让 Agent 真正具备“看视频”的能力,把一段视频拆成它能理解的帧序列和音频信息,再喂给模型做推理。
说白了,它不是一个播放器,也不是一个转码工具,而是一座桥——桥的一头是 ffmpeg 这套老牌音视频处理工具链,另一头是 Claude Code 这类 Agent 运行环境。桥搭好了,Agent 就能对视频做抽帧、提取关键画面、读取时长和分辨率、甚至配合语音转文字做内容理解。适合谁来参考?如果你正在用 Claude Code 做自动化,或者自己在写 Agent 框架、想让 Agent 处理多媒体输入,那这套思路你直接抄就行。哪怕你只是刚装完 Claude Code、还在摸索 Skill 机制的新手,跟着走一遍也能把整个链路跑通。
我先把结论摆在这:核心就三件事—— 用 ffmpeg 把视频拆成帧和音频 , 用 Skill 的目录结构和描述文件把能力注册给 Agent , 用一套约定好的调用协议让 Agent 知道什么时候该用它 。听起来简单,但每一步都有坑,下面我一个个拆。
2. 整体设计思路:为什么是 ffmpeg + Skill 这个组合
2.1 视频理解这件事,Agent 到底缺什么
先想清楚一个问题:Agent 处理视频,难点到底在哪?不是模型不够聪明,而是 输入格式对不上 。大模型的原生输入是 token 序列,图片可以切成 patch 变成 token,但视频是连续的帧流加音轨,直接塞进去既不现实也不经济。一段 10 分钟、30fps 的视频有 18000 帧,你不可能全喂进去。
所以正确的思路是 降维 :把视频这个高维连续信号,压缩成 Agent 能消化的离散信息。具体来说分两条线——视觉线抽关键帧,听觉线提音频转文字。抽帧不是随便抽,要按时间间隔或者场景变化来抽,保证抽出来的帧能代表视频的主要内容。音频线则交给语音识别,把说的话变成文本。这两条线合起来,Agent 就相当于“看了”这段视频。
claude-video 这个 Skill 的定位,就是把这套降维流程封装成一个 Agent 可以随时调用的能力。它不负责理解,理解交给模型;它只负责 把视频变成模型能理解的东西 。
2.2 为什么选 ffmpeg 而不是别的
音视频处理这个领域,ffmpeg 是绕不过去的。我试过用 Python 的 opencv 抽帧,简单场景够用,但一遇到各种奇葩编码格式就开始报错;也试过 moviepy,写起来舒服,底层还是调 ffmpeg,多一层封装反而多了出错的地方。ffmpeg 的好处是 格式支持全、命令行稳定、跨平台一致 ,你在 Linux 上跑通的命令,搬到 Windows 和 macOS 上基本不用改。
更重要的是,ffmpeg 的输出可以被精确控制。抽帧可以指定时间点、指定帧率、指定输出尺寸;提取音频可以指定采样率、声道数、编码格式。这些参数对 Agent 来说很关键——你抽出来的帧太大,token 消耗爆炸;太小,模型看不清细节。ffmpeg 让你能在这中间找到平衡点。
至于 Skill 这个形态,它是 Claude Code 生态里比较轻量的一种能力扩展方式。相比写一个完整的 MCP server,Skill 更像是一个“说明书 + 脚本”的组合,Agent 读到描述就知道这个能力是干嘛的、怎么调。对于 claude-video 这种“输入视频、输出帧和文本”的单一职责工具,Skill 的形态刚刚好,不用搞得太重。
2.3 整体架构长什么样
我把整个链路画成文字版,方便你理解数据怎么流动:
用户/Agent 传入视频路径
↓
claude-video Skill 被触发
↓
调用 ffmpeg 抽帧 → 输出到临时目录(jpg/png 序列)
调用 ffmpeg 提音频 → 输出 wav/mp3
↓
(可选)音频转文字 → 得到字幕文本
↓
返回给 Agent:帧文件路径列表 + 时长/分辨率元信息 + 文本
↓
Agent 读取帧图片 + 文本,交给模型做理解
这里有个设计取舍值得说: Skill 本身不做理解,只做转换 。为什么?因为理解是模型的事,Skill 如果掺和进去,就变成了一个黑盒,Agent 不知道中间发生了什么,出了问题也没法排查。保持 Skill 的“透明”,让它只负责把视频拆开、把零件摆好,Agent 拿到零件后自己决定怎么用,这样灵活性和可调试性都更好。
3. 核心细节解析:抽帧、提音频、元信息三件套
3.1 抽帧策略:抽多少帧才够用
抽帧是整个流程里最需要动脑子的地方。抽多了 token 爆炸,抽少了信息丢失。我的经验是分场景:
- 对话类视频 (访谈、课程):画面变化小,重点在音频,抽帧频率可以低,比如每 10 秒一帧,甚至只在场景切换时抽。
- 操作演示类 (教程、开箱):画面变化大,关键动作可能就一两秒,需要按固定间隔抽,比如每 2 秒一帧。
-
影视/短视频
:节奏快,建议用场景检测抽帧,ffmpeg 的
select滤镜可以做到。
ffmpeg 抽帧的基础命令是这样的:
ffmpeg -i input.mp4 -vf "fps=1/2" -q:v 2 frames/frame_%04d.jpg
这条命令的意思是:输入 input.mp4,用 fps 滤镜按每 2 秒抽一帧(
fps=1/2
表示每秒抽 1/2 帧,即 2 秒一帧),输出质量等级 2 的 jpg 到 frames 目录,文件名按 frame_0001.jpg 递增。
几个关键参数解释一下:
-
-vf "fps=1/2":抽帧频率。fps=1是每秒一帧,fps=1/2是两秒一帧,fps=2是每秒两帧。根据视频长度和内容密度调整。 -
-q:v 2:jpg 质量,范围 2-31,数字越小质量越高。2 已经很高了,一般用 2-5 就够。 -
frame_%04d.jpg:输出文件名模板,%04d表示 4 位数字补零,保证排序正确。
注意:抽帧前一定要先探测视频时长,否则你不知道会抽出多少帧。用
ffprobe可以拿到时长:
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
这条命令只输出时长秒数,干净利落,方便脚本里直接取值算帧数。
3.2 音频提取:为语音转文字做准备
音频这条线相对简单,但格式选择有讲究。语音识别模型一般对 wav 支持最好,采样率 16kHz、单声道是通用配置:
ffmpeg -i input.mp4 -vn -ac 1 -ar 16000 -acodec pcm_s16le audio.wav
参数含义:
-
-vn:不要视频流,只处理音频。 -
-ac 1:单声道。语音识别不需要立体声,单声道还能减小文件体积。 -
-ar 16000:采样率 16kHz。这是大多数语音识别模型的标准输入采样率,高了浪费,低了丢信息。 -
-acodec pcm_s16le:PCM 16 位小端编码,wav 的标准格式。
如果你的语音识别服务支持 mp3,也可以直接输出 mp3 省空间:
ffmpeg -i input.mp4 -vn -ac 1 -ar 16000 -b:a 64k audio.mp3
64k 码率对语音来说足够了,人声频段就那么宽,再高也听不出差别。
3.3 元信息提取:让 Agent 知道视频的“底细”
Agent 在决定怎么处理视频之前,需要先知道视频的基本信息:多长、多大、什么编码、多少帧率。这些用 ffprobe 一次性拿到:
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,duration -of json input.mp4
输出是 JSON 格式,方便程序解析。
-select_streams v:0
表示只看第一个视频流,避免拿到音频流的信息混淆。
拿到这些信息后,Agent 可以做判断:比如视频超过 30 分钟,就降低抽帧频率;分辨率超过 1080p,就先把帧缩小再输出,省 token。
3.4 Skill 的目录结构与描述文件
Claude Code 的 Skill 一般放在特定目录下,每个 Skill 一个文件夹,里面至少有一个描述文件(通常是 markdown 格式),告诉 Agent 这个 Skill 是干嘛的、什么时候用、怎么调。
一个典型的 claude-video Skill 目录结构:
claude-video/
├── SKILL.md # 描述文件,Agent 读这个决定是否调用
├── scripts/
│ ├── extract_frames.sh # 抽帧脚本
│ ├── extract_audio.sh # 提音频脚本
│ └── probe_video.sh # 元信息探测脚本
└── README.md # 给人看的说明
SKILL.md 的内容要写得让 Agent 一看就懂。核心是回答三个问题: 这个 Skill 能做什么 、 什么情况下该用它 、 怎么调用它 。比如:
---
name: claude-video
description: 当需要理解视频内容时使用。可以抽帧、提取音频、获取视频元信息。
---
# claude-video
让 Agent 具备处理视频的能力。
## 使用场景
- 用户提供了一个视频文件,需要分析内容
- 需要从视频中提取关键画面
- 需要把视频里的语音转成文字
## 调用方式
运行 scripts/extract_frames.sh <视频路径> <输出目录> <抽帧间隔秒数>
运行 scripts/extract_audio.sh <视频路径> <输出音频路径>
运行 scripts/probe_video.sh <视频路径>
描述文件里的
description
字段最关键,Agent 就是靠这句话判断要不要触发这个 Skill。写得太宽泛,Agent 动不动就调用;写得太窄,该用的时候想不起来。我的经验是
把触发条件写具体
,比如“当用户提供视频文件路径且需要分析内容时”,而不是笼统的“处理视频”。
4. 实操过程:从零把 claude-video 跑起来
4.1 环境准备:ffmpeg 安装的几条路
ffmpeg 安装是新手最容易卡住的地方,我按平台说清楚。
Linux(Ubuntu/Debian) :
sudo apt update
sudo apt install ffmpeg
装完用
ffmpeg -version
验证。如果提示找不到命令,检查 PATH。
macOS :
brew install ffmpeg
Homebrew 装的 ffmpeg 一般带全了常用编码器,够用。
Windows :
官网下载编译好的包,解压后把
bin
目录加到系统 PATH 里。注意选对版本,一般选 essentials 版本就够,full 版本体积大很多但多了些不常用的编码器。解压路径别带中文和空格,否则命令行调用容易出问题。
提示:如果你需要硬件加速(比如用 GPU 解码),Linux 下可以装带 nvidia 支持的 ffmpeg 版本,但普通抽帧提音频用不上,CPU 足够了。别为了这个折腾半天,除非你确实要处理大量高清视频。
装完后跑一条测试命令确认能用:
ffmpeg -f lavfi -i testsrc=duration=5:size=320x240:rate=30 -f null -
这条命令生成一个 5 秒的测试视频然后丢弃,不报错就说明 ffmpeg 工作正常。
4.2 抽帧脚本的完整实现
我把抽帧脚本写成一个带参数校验的 bash 脚本,这样 Agent 调用时不容易出错:
#!/bin/bash
# extract_frames.sh - 从视频中抽帧
# 用法: ./extract_frames.sh <视频路径> <输出目录> <抽帧间隔秒数>
set -e
VIDEO_PATH="$1"
OUTPUT_DIR="$2"
INTERVAL="${3:-2}" # 默认 2 秒一帧
if [ -z "$VIDEO_PATH" ] || [ -z "$OUTPUT_DIR" ]; then
echo "用法: $0 <视频路径> <输出目录> [抽帧间隔秒数]"
exit 1
fi
if [ ! -f "$VIDEO_PATH" ]; then
echo "错误: 视频文件不存在: $VIDEO_PATH"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
# 计算 fps 值:间隔 2 秒 → fps=1/2
FPS="1/$INTERVAL"
ffmpeg -i "$VIDEO_PATH" \
-vf "fps=$FPS" \
-q:v 3 \
"$OUTPUT_DIR/frame_%04d.jpg" \
-hide_banner -loglevel error
FRAME_COUNT=$(ls "$OUTPUT_DIR"/frame_*.jpg 2>/dev/null | wc -l)
echo "抽帧完成,共 $FRAME_COUNT 帧,输出到 $OUTPUT_DIR"
几个细节说明:
-
set -e:任何命令出错就退出,避免错误被忽略。 -
INTERVAL="${3:-2}":第三个参数可选,默认 2 秒。 -
-hide_banner -loglevel error:隐藏 ffmpeg 的版本信息和进度输出,只显示错误,让脚本输出干净。 - 最后统计帧数,方便 Agent 知道抽了多少。
4.3 提音频脚本与语音转文字衔接
提音频脚本类似:
#!/bin/bash
# extract_audio.sh - 从视频中提取音频
# 用法: ./extract_audio.sh <视频路径> <输出音频路径>
set -e
VIDEO_PATH="$1"
AUDIO_PATH="$2"
if [ -z "$VIDEO_PATH" ] || [ -z "$AUDIO_PATH" ]; then
echo "用法: $0 <视频路径> <输出音频路径>"
exit 1
fi
ffmpeg -i "$VIDEO_PATH" \
-vn -ac 1 -ar 16000 -acodec pcm_s16le \
"$AUDIO_PATH" \
-hide_banner -loglevel error
echo "音频提取完成: $AUDIO_PATH"
拿到 wav 之后,接语音识别。如果你用的是本地模型(比如 whisper 系列),直接跑就行;如果用云端 API,把 wav 传上去拿文本。这一步不在 Skill 内部做,而是交给 Agent 决定用哪个识别服务,保持灵活性。
4.4 元信息探测脚本
#!/bin/bash
# probe_video.sh - 获取视频元信息
# 用法: ./probe_video.sh <视频路径>
set -e
VIDEO_PATH="$1"
if [ ! -f "$VIDEO_PATH" ]; then
echo "错误: 视频文件不存在: $VIDEO_PATH"
exit 1
fi
ffprobe -v error \
-select_streams v:0 \
-show_entries stream=width,height,r_frame_rate,duration \
-show_entries format=duration,size \
-of json \
"$VIDEO_PATH"
输出 JSON 里包含宽高、帧率、时长、文件大小,Agent 解析后就能做决策。
4.5 在 Claude Code 里注册并调用
把 claude-video 文件夹放到 Claude Code 的 skills 目录下(具体路径看你的安装配置,一般在用户目录下的
.claude/skills/
或者项目内的
.claude/skills/
)。放好后重启 Claude Code,或者用它的 skill 重载命令。
验证是否注册成功:在对话里问一句“你能处理视频吗”,如果 Agent 提到了 claude-video 的能力,说明注册成功。
实际调用时,你直接说“帮我分析一下这个视频 /path/to/video.mp4”,Agent 会自己判断触发 claude-video,先探测元信息,再抽帧提音频,最后把帧和文本拿去做理解。整个过程你只需要给一个视频路径。
注意:Skill 的触发依赖描述文件的
description字段,如果 Agent 没触发,先检查这个字段写得够不够明确。我踩过的坑是描述写得太学术,Agent 理解不了,改成大白话“当用户提供视频文件需要分析时使用”就正常了。
5. 常见问题与排查技巧实录
5.1 抽帧相关的高频问题
问题一:抽出来的帧是黑的或者花屏。
这通常是视频编码格式特殊,或者 ffmpeg 版本太老不支持。先升级 ffmpeg 到较新版本,再试。如果还不行,加
-vsync vfr
参数让 ffmpeg 按可变帧率处理:
ffmpeg -i input.mp4 -vf "fps=1/2" -vsync vfr -q:v 3 frames/frame_%04d.jpg
问题二:抽帧数量远超预期。
检查视频时长和抽帧间隔。如果视频是 1 小时,间隔 2 秒,那就是 1800 帧,确实多。这种情况要么加大间隔,要么先用场景检测只抽关键帧:
ffmpeg -i input.mp4 -vf "select='gt(scene,0.3)',showinfo" -vsync vfr frames/frame_%04d.jpg
gt(scene,0.3)
表示场景变化超过 30% 才抽,能大幅减少帧数。
问题三:输出目录不存在导致失败。
脚本里已经用
mkdir -p
处理了,但如果你手动跑命令,记得先建目录。这是新手最常见的错误,ffmpeg 不会自动创建输出目录。
5.2 音频提取的坑
问题一:提取的音频没声音。
检查原视频是不是本来就没音轨。用
ffprobe
看有没有 audio stream:
ffprobe -v error -select_streams a -show_entries stream=codec_name -of default=noprint_wrappers=1 input.mp4
没输出就说明没音轨,不是提取的问题。
问题二:音频文件太大。
wav 是无损的,体积大正常。如果只是做语音识别,转成 mp3 或 opus 能小很多:
ffmpeg -i input.mp4 -vn -ac 1 -ar 16000 -b:a 32k audio.opus
opus 在低码率下语音质量比 mp3 好,32k 就够用。
5.3 Skill 调用层面的问题
问题一:Agent 不触发 Skill。
三个排查方向:描述文件的
description
是否明确、Skill 目录位置是否正确、Claude Code 是否重启加载。我遇到过目录放对了但没重启,Agent 一直看不到的情况。
问题二:脚本没有执行权限。
Linux/macOS 下脚本需要可执行权限:
chmod +x scripts/*.sh
Windows 下用 git bash 或者 wsl 跑,别用 cmd 直接跑 bash 脚本。
问题三:路径里有空格或中文导致失败。
脚本里变量加引号
"$VIDEO_PATH"
能处理空格,但中文路径在某些环境下仍有问题。建议处理前先把视频复制到纯英文路径下。
5.4 常见问题速查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 抽帧全黑 | 编码不支持 |
升级 ffmpeg,加
-vsync vfr
|
| 帧数过多 | 间隔太小 | 加大间隔或用场景检测 |
| 音频无声 | 原视频无音轨 | 用 ffprobe 确认 |
| Agent 不触发 | 描述不明确 | 改 description 为具体场景 |
| 脚本无权限 | 未加执行权限 |
chmod +x
|
| 路径报错 | 空格/中文 | 加引号,复制到英文路径 |
5.5 几个我踩过的坑和独家技巧
技巧一:抽帧前先缩放,省 token。 如果视频是 4K,抽出来的帧也是 4K,喂给模型 token 消耗巨大。加个 scale 滤镜先缩到 720p:
ffmpeg -i input.mp4 -vf "fps=1/2,scale=1280:-1" -q:v 3 frames/frame_%04d.jpg
scale=1280:-1
表示宽度缩到 1280,高度按比例自动算。模型看 720p 的帧足够理解内容了。
技巧二:用临时目录,别污染工作区。
抽帧会产生大量文件,建议输出到
/tmp
或系统临时目录,处理完让 Agent 自己清理。我在脚本里加了个清理逻辑,处理完自动删帧,避免磁盘被塞满。
技巧三:长视频分段处理。
超过 30 分钟的视频,一次性抽帧可能几百上千张,Agent 处理不过来。可以按时间分段,每段单独抽帧,Agent 逐段分析。ffmpeg 的
-ss
和
-t
参数可以指定起始时间和时长:
ffmpeg -ss 00:10:00 -t 00:05:00 -i input.mp4 -vf "fps=1/2" frames/part2_%04d.jpg
注意
-ss
放在
-i
前面是快速定位,放在后面是精确但慢。抽帧用快速定位就够。
技巧四:帧文件名要能排序。
%04d
补零到 4 位,保证 frame_0001 到 frame_9999 排序正确。如果视频帧数可能超过 9999,用
%05d
。
6. 这套方案还能怎么扩展
claude-video 目前做的是“视频转帧 + 音频转文本”的基础能力,但它的扩展空间很大。我自己在用的几个方向:
方向一:接 OCR 做画面文字提取。 抽出来的帧如果有字幕、PPT、界面文字,可以再过一道 OCR,把画面里的文字也变成文本。这样 Agent 对视频的理解就从“画面 + 语音”扩展到“画面 + 语音 + 画面文字”,信息更全。
方向二:场景检测替代固定间隔。 固定间隔抽帧在画面变化剧烈时会漏掉关键帧,在画面静止时又浪费帧。用 ffmpeg 的 scene 检测滤镜,只在画面变化时抽帧,效率更高。我实测下来,对教程类视频,场景检测能减少 60% 的帧数,但关键信息一个不丢。
方向三:和 Agent 的记忆机制结合。 处理过的视频,把抽帧结果和文本摘要存起来,下次遇到同一个视频直接读缓存,不用重复处理。这对批量处理场景很有用。
方向四:支持更多输入源。 目前是本地视频文件,扩展到网络视频流、摄像头实时流也是可行的,ffmpeg 本身就支持这些输入。不过实时流处理对延迟要求高,需要另做优化。
我个人在实际操作中的体会是,Skill 这类工具的价值不在于功能多复杂,而在于 边界清晰、职责单一 。claude-video 就干一件事——把视频拆成 Agent 能吃的格式,拆完就退场,剩下的交给模型。这种设计让整个链路可调试、可替换、可扩展。你如果也在做 Agent 的多媒体能力,建议从这种“单一职责”的 Skill 开始,别一上来就搞大而全的框架,先把一个场景跑通,再逐步加能力。踩过几次坑之后你会发现,能稳定跑通的基础能力,比花哨但脆弱的复杂功能有用得多。
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)