我已经在这条路上踩了不少坑,今天分享出来,希望让你少走弯路。

先把话放前面: 这篇文章的主角是 claude-video,一个给 Agent 增加视频理解能力的 Skill 。它能解决一个特别具体的问题——你平时指挥 AI Agent 干活,它能读文档、能写代码、能上网查资料,但一遇到视频就哑火了,只会回一句“我无法直接解析视频内容”。这太扫兴了。我的需求也很朴素:让 Agent 能看一段视频,然后回答“视频里讲了什么”“画面里出现过哪些关键信息”“某个时间点发生了什么”。

这篇文章我会从背景动机、Skill 的运行机制、核心实现、实测效果、踩坑记录到扩展方向,完整交代清楚,适合正在做 Agent 开发、想给自己的智能体增加多模态能力的开发者参考。就算你目前对 Skill 机制还不熟,读完也会知道它是怎么回事,以及下一步该抄哪些作业。

1. 视频为什么一直是 Agent 的盲区:从一次被拒的经历说起

先讲个真实场景。之前我在做一个自动化的信息整理流程,想让我自己的 Agent 帮忙把一段产品发布会录像提炼成文字纪要。结果它拿到视频文件之后,直接告诉我:“当前环境无法处理视频文件,建议先转成文本。”我当时就意识到, 问题根本不在 Agent 不会思考,而是它缺少一根“视频解码”的神经 。

如果你拆开看,会发现这里有两层障碍:

  • 第一层是技术障碍。主流大模型 API 虽然多模态能力越来越强,但大多数场景下,Agent 拿到的输入仍然是“文字 + 图片”的组合。视频是连续的媒体流,直接丢给它,它既不能播放,也没有“眼睛”逐帧去看,更没有内置的音频转写能力。
  • 第二层是交互障碍。就算你给 Agent 一个视频文件的路径,它也不知道该用什么工具去打开、去抽帧、去提取音频。它需要有人告诉它:你可以这样做、用那个工具、先做哪一步再做哪一步。这本质上是一种“能力的前置编排”。

Skill 就是来解决第二层问题的。

你可能听过“Agent 框架”“Skill 插件”这些词,听起来高大上,其实把它们看成“给 Agent 配的说明书 + 工具箱”就行。Skill 的核心是一个结构化的指令包,通常包含一个描述文件(比如 SKILL.md),里面写了“这个技能是干嘛的、在什么场景下调用、需要哪些环境依赖、完成任务的步骤是什么”。Agent 在收到用户请求后,会在自己的技能清单里检索匹配项,找到合适的 Skill,然后按里面的指引结合工具去执行任务。

claude-video 这个 Skill,做的事情就是把“视频 → 可读信息”这条链路封装起来。它让 Agent 在看到 .mp4、.mov、.webm 这类文件时,不再说“我看不了”,而是说“稍等,我先抽帧、转写、再分析”。

这里要强调一个关键认知: Agent 的“看视频”不是像人一样连续地观看,而是把视频拆解成一帧一帧的图片、一段一段的语音文本,再靠大模型的视觉理解和文本理解能力把信息缝合起来。 想清楚这一点,很多设计决策就都顺了。

2. Skill 到底是啥:给 Agent 装“技能插件”的机制速览

既然标题里带了 Skill,我先把这套机制讲透,不然你后面看代码和配置会有种“每个字都认识,连起来不知道在干嘛”的感觉。

2.1 从 Agent 到 Skill:一层抽象,换来十倍扩展性

Agent 本身是一个具备对话、规划、调用工具能力的执行体。它的核心是用大模型做决策,选出下一步该执行什么动作。工具(Function Call)是它操作外部世界的手,而 Skill 则是对“手的使用方法”的封装。

打个比方:Agent 是一个新来的实习生,大模型是他的大脑,工具电话、电脑、打印机是他的设备,Skill 就是一本本操作手册。“怎么用打印机双面打印”是一本手册,“怎么把一份视频转成图文报告”是另一本手册。没有手册,实习生只能干瞪眼;有了手册,他按步骤操作就行。

Skill 比单纯给 Agent 写 prompt 强的地方在于 模块化和复用性 。你把一个复杂任务的知识、步骤、依赖、备选方案都写进 Skill 文件里,它就能被不同的 Agent 项目共享。今天在 Claude 上用,明天换到别的支持 Skill 机制的框架里,也可以低成本迁移。

2.2 SKILL.md:一台“自助售货机”的操作说明

大部分 Skill 框架都会约定一个 markdown 文件作为入口,常见命名是 SKILL.md。这个文件里通常会写清楚:

  • 技能名称和描述 :用于 Agent 做意图匹配,描述写得越准确,Agent 越知道什么时候该调用它。
  • 适用场景 :什么类型的输入该走这个技能,什么情况下不该用。
  • 执行步骤 :这是核心部分,把大任务拆成有序的小步骤,每一步该用什么命令、工具、参数。
  • 注意事项 :错误处理、资源限制、输出格式要求。

claude-video 的设计也遵循这个套路,但在执行步骤上做了很多自定义扩展,因为视频处理的可变因素太多了,视频编码不同、时长不同、音频清晰度不同,都会影响后续的转录和分析效果。

2.3 为什么选择 Skill 而不是直接代码写死

我自己以前写过那种硬编码的视频处理脚本:输入视频路径,输出分析结果。这种方案的缺点很明显——换一个任务场景就得改代码,而且 Agent 的灵活性完全发挥不出来。Skill 方案则把“决策”留给大模型,把“执行”交给工具,中间用可读文本串联。

举个例子:同样一个 claude-video Skill,你让 Agent“总结这段视频讲了什么”,它走的是抽帧摘要 + 音频转写的路径;你让它“找出视频里所有的产品名称”,它走的还是这套路径,但会在分析阶段侧重 OCR 识别画面文字、重点听语音里的专有名词。代码可以不改,变的是 Agent 根据用户需求,在 Skill 框架内灵活组织每一步。这种“框架固定,用法灵活”的特性,正是我最终选定 Skill 方案的根本原因。

3. 三条技术路线对比:为什么我最终选择截帧 + 转写 + 拼接

在动手写 claude-video 之前,我认真盘过三条路线,各有适用场景,我把对比结果放在这里。

路线 核心思路 优点 缺点 适用场景
视频直接喂多模态 API 把完整视频传给支持视频理解的大模型接口 语义连贯性好,模型能理解运动关系 成本极高,大量视频格式不支持,平台绑定严重 短片段、高质量 API 预算充足
截帧 + 图像理解 用 ffmpeg 抽帧,逐张交给视觉模型分析 实现简单,通用性强,可控性高 丢失时序信息,可能漏掉关键瞬间 大多数通用视频分析场景
音频转写 + 截帧结合 音频走语音识别,画面走抽帧,最后二次融合 信息互补,覆盖画面和语音两条线索 实现复杂度稍高,需要做时间对齐 信息密度高的视频,如课堂、会议、发布会

claude-video 最终选择的是第三条路,这是当前工程性价比最高的组合。

实际落地的时候还有一个细节: 不是所有视频都需要完整走两条链路 。如果一个视频主要是放 PPT,画面信息重要,那我会提高抽帧频率;如果是一段播客访谈,画面几乎不动,那音频转写才是主角。所以我在 Skill 的实现里留了策略开关,Agent 可以根据视频类型自己调整参数。这个设计后面展开讲。

要补充的是,视频处理很吃机器资源,尤其长视频。所以我默认加了时长上限配置,超过一定时长的视频会先做分段处理再合并,避免把 Agent 的执行环境拖垮。

4. 动手实现 claude-video:目录结构、配置项和核心流程

这里开始上硬货。我带你把整个 Skill 从零搭一遍,包括目录组织、关键配置、每个模块的职责划分。看完这一部分,你完全可以按同样思路给自己做一个 Skill,不一定局限于视频,换成音频、PDF 甚至数据分析都行。

4.1 整体目录结构:一个 Skill 该长什么样

claude-video 的目录结构我这么组织:

claude-video/
├── SKILL.md
├── assets/
│   └── sample_config.json
├── scripts/
│   ├── extract_frames.py
│   ├── transcribe_audio.py
│   ├── merge_results.py
│   └── utils.py
├── prompts/
│   └── analysis_guidelines.md
└── requirements.txt
  • SKILL.md :技能说明文档,Agent 首先读它。
  • scripts/ :实际执行任务的 Python 脚本,每个脚本职责单一。
  • prompts/ :分析阶段的提示词模板,用来指导大模型如何解读抽帧结果和转写文本。
  • requirements.txt :依赖清单,如 opencv-python、openai-whisper、ffmpeg-python 等。

这种“说明文件 + 脚本 + 提示词模板”的三段式结构,基本上是一个 Skill 的标准范式了。你以后自己写别的技能,直接套这套骨架就行。

4.2 SKILL.md:Agent 的行为指南

SKILL.md 是整个 Skill 的灵魂。它不像普通代码那样被执行,而是被大模型阅读理解后转化为行动计划。所以我写的时候特别在意“描述准确性”和“步骤可操作性”。

下面是精简过的关键内容结构:

# claude-video

## 描述
分析视频文件内容,提取关键画面和语音信息,生成结构化文字摘要。

## 适用场景
- 用户输入 .mp4 / .mov / .webm 等视频文件
- 需要回答“视频里讲了什么”“出现了哪些内容”“哪些时间点有重要事件”

## 执行步骤
1. 检查视频文件是否存在,确认格式和大小。
2. 调用 extract_frames.py 按设定间隔抽帧,保存为临时图片。
3. 调用 transcribe_audio.py 提取音频并转写为带时间戳的文本。
4. 将图片按时间顺序排列,配合转写文本,调用分析提示词生成最终回答。
5. 清理临时文件。

## 注意事项
- 视频时长超过 30 分钟时,建议先分段再逐段处理。
- 抽帧间隔要根据视频类型动态调整,动态场景使用 1 秒 1 帧,静态场景可放宽到 10 秒 1 帧。
- 如果音频转写置信度低,在回答中明确标注“该部分听写结果可能不准确”。

这里每一段都有讲究。“描述”决定了 Agent 什么时候想起这个 Skill,写得太泛,它会在不该调用的时候瞎调用;写得太窄,关键时刻它又想不到。我的经验是,多写几个典型场景的例句,匹配率会高很多。

“执行步骤”的部分,我刻意把顺序写得非常明确。因为大模型在 Agent 里做规划时,步骤越清晰,越不容易自己发明一套奇怪流程。比如让它“检查文件是否存在”,避免后面脚本报错时 Agent 一脸懵不知道怎么回事。

4.3 抽帧模块:视频的“眼睛”长什么样

视频的本质是快速切换的连续图片。Agent 要“看”,就必须把这些连续图片抽样成离散的几张。

我用的是 OpenCV 的 VideoCapture。它的优点是对比 ffmpeg 命令行更 Pythonic,而且能直接拿到帧数据,方便后续用 PIL 再做压缩或裁剪。

核心代码逻辑不复杂,我提炼一下精华:

import cv2
import os

def extract_frames(video_path, output_dir, interval_seconds=5):
    cap = cv2.VideoCapture(video_path)
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_interval = int(fps * interval_seconds)
    frame_count = 0
    saved_count = 0
    os.makedirs(output_dir, exist_ok=True)

    while True:
        ret, frame = cap.read()
        if not ret:
            break
        if frame_count % frame_interval == 0:
            out_path = os.path.join(output_dir, f"frame_{saved_count:04d}.jpg")
            # 适当压缩宽度,避免单张图过大
            height, width = frame.shape[:2]
            if width > 1280:
                scale = 1280 / width
                frame = cv2.resize(frame, (1280, int(height * scale)))
            cv2.imwrite(out_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 85])
            saved_count += 1
        frame_count += 1

    cap.release()
    return saved_count

这里有两个容易被忽略的细节。

第一, 抽帧间隔不是越小越好 。间隔太小,一小时的视频会抽出几千张图,视觉模型处理不完,费用也爆炸。我调研发现,对于大多数“视频画面变化不剧烈”的场景,每 5 秒抽 1 帧已经足够。如果是体育比赛、舞蹈这类动态场景,再降到 1-2 秒。

第二, 抽出来的图要压缩 。原始帧可能是一张 4K 超大图,直接传给视觉模型,token 消耗惊人。我在脚本里限制宽度不超过 1280,JPEG 质量 85,视觉信息损失可以接受,但成本能省一半以上。这就属于那种“文档里不会写、实操中才发现的坑”。

4.4 音频转写模块:让 Agent 把话说“听”见

画面之外,视频里还有一半信息在语音里。我的实现是用 openai-whisper 做本地转写。选它而不是云端 API 的原因很简单: 这个 Skill 得支持离线环境 ,而且本地跑能省掉视频上传的时间。

whisper 使用不难,难在如何输出“适合后续分析”的结果。如果只输出纯文本,时间戳信息就丢了,后续就没法和画面的时间轴对齐。所以我的做法是让它输出带起始时间、结束时间的 segment 列表。

import whisper

def transcribe_audio(video_path, model_size="base"):
    model = whisper.load_model(model_size)
    result = model.transcribe(video_path, verbose=False)
    segments = []
    for seg in result["segments"]:
        segments.append({
            "start": seg["start"],
            "end": seg["end"],
            "text": seg["text"].strip()
        })
    return segments

模型大小的选择也是个权衡。base 模型速度快,但识别准确率一般;large-v3 准确率高,但资源占用吓人,普通 CPU 机器跑起来像老牛拉车。我的建议是,预算允许就上 small 或 medium,如果对准确率有硬性要求再考虑 large。实际使用中,我发现 medium 在中文语音识别上的表现已经够用,偶尔有错别字但不影响理解。

另外要提一点,whisper 处理长视频时会非常慢。所以我在脚本里加了分段逻辑,每 10 分钟一段,逐段转写,再把结果合并。这样至少能保证进度可控,不至于跑了半小时最后 OOM 崩溃。

4.5 融合分析模块:画面和语音的信息怎么缝合

抽帧和转写这两条线是并行跑的。最后一步,需要把图片和文本按时间轴缝合起来,形成一个 Agent 能直接理解的信息包。

我的做法很简单但很有效—— 把时间轴作为锚点 。若干个连续抽帧配上一段对应时间窗口内的转写文本,编成一个“片段块”,每个片段块之间用时间标签分隔。这样大模型在处理时,既能看到这个时间段的画面,又能看到这段时间说了什么话,上下文就齐了。

{
  "video_id": "demo",
  "segments": [
    {
      "start_time": 0,
      "end_time": 30,
      "frames": ["frame_0000.jpg", "frame_0005.jpg", "frame_0010.jpg"],
      "transcript": "大家好,欢迎来到产品发布会……"
    },
    {
      "start_time": 30,
      "end_time": 60,
      "frames": ["frame_0015.jpg", "frame_0020.jpg", "frame_0025.jpg"],
      "transcript": "接下来我们介绍第二代产品的核心功能……"
    }
  ]
}

这个 JSON 结构就是大模型的“眼睛和耳朵”。在分析阶段,我把这个结构连同分析提示词一起发给模型,让它回答用户的原始问题。因为信息已经按时间轴组织好了,模型不仅能回答“讲了什么”,还能回答“大概在什么时间讲了什么”。这个能力在实际场景里非常有用,比如“帮我找到视频里提到价格的那一段”,模型就能直接指向具体时间位置。

分析提示词的引导也很关键。我写了一个 prompts/analysis_guidelines.md,里面会强调:回答时要优先引用画面中的可视信息,再补充语音转写内容;如果两者有冲突,明确指出;输出格式用 Markdown 分点,方便阅读。这属于 prompt 工程的细节,但对输出质量影响很大。

4.6 一个重要的设计:策略开关

前面我提过,不同视频的信息侧重不一样。所以我在 sample_config.json 里放了一组策略开关:

{
  "default_frame_interval": 5,
  "dynamic_scene_interval": 1,
  "static_scene_interval": 10,
  "enable_audio_transcribe": true,
  "enable_ocr": false,
  "max_duration_minutes": 30,
  "output_format": "markdown"
}

Agent 在处理视频前,可以先识别视频类型,再决定用哪套参数。比如识别到是“课堂录屏”,画面通常是大段固定 PPT,就把抽帧间隔调到 10 秒,省资源;识别到是“产品演示”,里面可能有频繁的操作变化,就调成 2 秒。这一步要不要做,取决于你的使用场景是否多样化。我做进去之后,实测对不同视频的适配效果好很多。

5. 实测效果:它到底“看”懂了多少

跑通不等于真的好用,所以我专门拿了几类视频做测试,这里把结果分享给你参考。

5.1 一段 15 分钟的科技发布会视频

这是我最常用的测试样片,信息密度高,画面和语音都有大量可提取内容。实测下来,最终生成的纪要能准确概括产品名、发布时间、核心功能亮点,还能定位到每个功能在视频中出现的秒级位置。

不过也暴露了一个明显短板:当我问“主持人今天的穿着是什么颜色”这种高度依赖单帧细节的问题时,模型的回答不稳定,有时说深色有时说浅色。原因也好理解——抽帧间隔 5 秒,万一那个瞬间没有抽到,或者画面压缩后颜色信息丢失,模型就只能猜了。这类问题要改善,得靠提高抽帧频率或引入局部视频片段再分析,属于后续优化的方向。

5.2 一段 1 小时的线上讲座

这种场景画面变化慢,信息主要在语音里。我把抽帧间隔默认调到了 10 秒,音频转写是绝对主力。

转写出的文本大概有小一万字,whisper medium 模型出现了少量同音字错误,比如把“正则表达式”听成“整合表达式”。这种错误不影响大局,但如果你要拿它做精确引用,就得留意修正。融合分析的效果不算差,它能根据画面里的 PPT 截图为转写文本补充上下文,生成的摘要结构清晰、重点突出,直接可以当作会议纪要初稿用。

5.3 一段无音频的纯画面剪辑

没有音轨就失去了一路信息源,所有理解都只能靠画面。这种情况下,截帧的密度就得提上来,我用的是 1 秒 1 帧。

测试下来,它能识别出画面主体(人物、场景、大致的物体),但对剪辑节奏、镜头语言的把握很弱。这也符合预期,毕竟它“看”的是离散的照片序列,不是连续的视频流。如果你想做更深入的视频风格分析,这套方案确实不适合,得换专门的视频理解模型。

5.4 性能数据,一句话总结

10 分钟 1080p 视频,在带 GPU 的机器上完整跑一遍,抽帧大概十几秒,转写大约两三分钟,分析阶段看模型输出耗时。在纯 CPU 机器上,转写时间会拉长到十分钟以上。所以有条件就上 GPU,体验差距很大。

6. 安装配置与踩坑记录:三件最容易被新手玩坏的事

如果看完上面你准备自己试,下面这三个坑务必要提前避掉,都是我在开发过程中真实遇到的,每一个都让我折腾了不短时间。

6.1 ffmpeg 装了但 Python 调不到

OpenCV 和 whisper 底层都依赖 ffmpeg,但系统装了 ffmpeg 不代表 Python 就能直接用。我一开始在本机上用 Homebrew 装了 ffmpeg,脚本跑起来一直报编码错误,排查半天,最终发现是 PATH 环境变量的问题——Python 进程没找到 ffmpeg 可执行文件。

解决方式其实就一句:安装 ffmpeg 后,重启终端或代码运行环境,让 PATH 生效。另外你也可以在 Python 脚本里手动指定 ffmpeg 路径,避免环境变量干扰。还有一个小建议:不要把不同渠道装的 ffmpeg 混在一起,有些打包工具自带的 ffmpeg 版本可能缺部分编解码器,换一个版本行为又不一样,很容易踩坑。

6.2 视频文件损坏但不报错

OpenCV 的 VideoCapture 在打开损坏或不完整的视频时,不一定报错,read() 会在某一帧后一直返回 False,脚本就静默结束了。如果我只看输出文件数量,会误以为处理成功。

我的防御措施是:读取完视频后,主动比对“已保存帧数”和“预期帧数”。预期帧数可以通过时长乘帧率算出来。两者差距太大,我就判定文件异常,让 Agent 给用户明确提示,避免撒谎式输出。这个机制加上之后,整个 Skill 的可信度提升了一个档次。

6.3 临时文件清理不及时

抽帧和转写中间过程会产生大量临时文件。一开始我图省事,没做清理,跑了几次之后临时目录占了好几个 GB。后来我在 Skill 的执行步骤末尾强制加了清理环节,并且用 try/finally 保证异常时也能清理。因为 Agent 执行环境通常有磁盘空间限制,这类小事不处理好,迟早拖垮你。

7. 从 claude-video 到通用“百宝箱”:Skill 还能扩展出什么花样

做完 claude-video 之后,我有一个特别直观的感受: Skill 机制的想象空间比想象中大得多 。视频能力只是其中一个分支,同样一套“抽帧 + 转写 + 融合分析”的骨架,稍微改造就能做很多事。

比如音频类 Skill。把截帧部分去掉,专注做音频转写、说话人分离、语气情感分析,可以做出一个能“听会议”的 Agent。再比如文档类 Skill,把文件解析出来之后,让 Agent 对多份文档做交叉比对、提取差异点。甚至还能做网页类 Skill,抓取页面内容、识别页面布局、提取结构化信息。

关键在于,Skill 剥离了具体工具的差异,统一用“描述 + 步骤 + 依赖”来定义能力边界。Agent 不再是一堆散装工具的搬运工,而是能根据任务目标灵活调用不同 Skill 的执行官。这套模式配合上多模态大模型的发展,以后 Agent 能处理的信息类型会越来越丰富,视频也只是其中一块拼图而已。

如果你要自己写一个 Skill,我最后一条建议是: 从你自己最频繁的重复劳动里找切入点 。不要为了写而写,应该是“这件事我每周都做,很烦,那让 Skill 替我干”。带着这种真需求去设计,写出来的东西才会有灵魂,而不是一个摆设。现在这个 claude-video 已经在我自己的自动化流程里稳定跑了一个多月,每次看到它能帮我把十几分钟的视频内容变成一页清晰的纪要,我都觉得当初花时间把这条路打通是值得的。

Logo

邀请您加入社区

更多推荐