news 2026/8/31 13:24:14

AI Agent + Skill 实现自动化视频剪辑:转写、脚本、渲染全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent + Skill 实现自动化视频剪辑:转写、脚本、渲染全流程

视频剪辑里最耗时间的不是“动手剪”这个动作,而是看完素材、做取舍、找剪辑点、反复调整的过程。最近我尝试用 AI Agent 做自动化剪辑,把整条流程拆成了 3 个 Skill:素材分析与转写、剪辑脚本生成、FFmpeg 渲染执行。跑通之后,从原始视频到成片基本可以做到“人工只审核,不手拖时间轴”。

这篇文章会把这条链路完整写一遍,包括 Skill 的组织方式、每个 Skill 的 SKILL.md 和配套脚本、FFmpeg 参数怎么选、中间产物怎么设计,以及跑通后踩到的几个典型问题。适合已经接触过 Claude Code、Codex 等支持 Skill 机制的 Agent 工具,但又不知道拿它做什么实际项目的开发者;也适合想用 AI 剪辑提高短视频生产率的博主或内容团队。

下面按“机制理解 -> 环境准备 -> 3 个 Skill 逐一实现 -> 串联运行 -> 排错 -> 生产建议”的顺序展开。

1. 先理解 Skill 在 AI 自动化剪辑中的定位

1.1 什么是 Skill,它解决什么问题

Skill 可以理解成一个“带说明书的能力包”。在 Claude Code、Codex 以及很多 Agent 框架里,Skill 通常由两部分组成:

  • SKILL.md:告诉 Agent 这个能力什么时候用、怎么用、有什么约束。
  • 配套脚本、提示词模板、参考文件:真正执行能力所需的材料。

没有 Skill 时,Agent 面对“帮我剪一段视频”这类任务,往往要反复追问用户,而且每次执行逻辑都可能飘。有了 Skill,Agent 会先读到固定规则,再按规则完成输入、处理、输出,结果稳定很多。

放到自动化剪辑场景里,Skill 的价值尤其明显:剪辑不是一个动作,而是一条流水线。流水线的每一步都有明确输入和输出,正好适合拆成独立 Skill。

1.2 为什么把剪辑流程拆成 3 个 Skill

我最初想用一个 Skill 搞定剪辑,结果发现上下文太长、Agent 经常混淆“先转写还是先剪”,而且中间产物无法复用。于是拆成 3 个,职责非常清楚。

Skill 名称职责输入输出
transcribe素材分析与转写原始视频文件带时间戳的文本和素材清单
script_builder剪辑脚本生成转写文本、素材清单结构化剪辑脚本 JSON
rendererFFmpeg 渲染执行剪辑脚本 JSON、原始素材最终成片 MP4

拆开之后,每个 Skill 的上下文都很短,Agent 不需要在一个提示词里同时处理视频文件、字幕文本和 FFmpeg 参数。出了问题时,也只要排查对应环节。

1.3 Skill 之间的数据流

数据流如下:

原始视频 -> Skill 1: transcribe -> transcript.json + materials.json -> Skill 2: script_builder -> edit_script.json -> Skill 3: renderer -> final.mp4

关键是中间产物必须是结构化数据。之前我用纯文本传结果,Agent 很容易解析错;改成 JSON 后,渲染脚本可以直接读取,不再依赖大模型二次猜测。

2. 准备视频剪辑工作台:环境、依赖与目录规范

2.1 环境要求

建议在 Linux 或 macOS 上跑,Windows 也能跑,但路径和编码问题会多一些。Python 版本建议 3.10 及以上。

软件版本建议用途
Python3.10+运行各 Skill 脚本
FFmpeg4.4+视频解析、剪辑、渲染
Whisper / faster-whisper最新稳定版语音转写
ffprobe随 FFmpeg 安装检查视频参数

这里的 Whisper 用于把视频里的语音转成带时间戳的文本,是后续剪辑脚本生成的依据。faster-whisper 在 CPU 上的转写速度通常比原版 Whisper 快,如果你的机器没有独立显卡,优先选它。

2.2 安装核心依赖

在 Ubuntu/Debian 上先装系统依赖:

sudo apt update sudo apt install -y ffmpeg python3-venv python3-pip

macOS 使用 Homebrew:

brew install ffmpeg python

然后创建 Python 虚拟环境并安装转写依赖:

mkdir -p ~/video-agent cd ~/video-agent python3 -m venv .venv source .venv/bin/activate pip install faster-whisper

验证 FFmpeg 是否可用:

ffmpeg -version ffprobe -version

如果输出版本信息正常,说明后续渲染环节的基础工具已经就绪。

2.3 工作目录和输入输出规范

目录结构如下:

video-agent/ ├── skills/ │ ├── transcribe/ │ │ ├── SKILL.md │ │ └── run.py │ ├── script_builder/ │ │ ├── SKILL.md │ │ └── run.py │ └── renderer/ │ ├── SKILL.md │ └── run.py ├── input/ ├── output/ └── work/
  • input/:放原始素材,所有 Skill 只读这个目录。
  • work/:放中间产物,如转写结果、剪辑脚本 JSON。
  • output/:放最终成片。

目录规范的意义是让 3 个 Skill 有共同约定。Skill 不关心文件从哪里来,只关心按约定路径读写,这样每个 Skill 都可以单独调试。

3. 第一个 Skill:素材分析与转写

3.1 Skill 的目标和输出

第一个 Skill 的目标是把“一段视频”变成“一段可阅读、可检索、可定位的文字”。

输出包括两部分:

  • transcript.json:每句语音的起止时间、文本内容。
  • materials.json:素材本身的时长、分辨率、编码信息。

以后剪辑脚本生成时,只看这两个文件,就能决定哪句话留下、哪句话删掉、哪个片段作为结尾。

3.2 SKILL.md 的写法

skills/transcribe/SKILL.md中写明触发条件、步骤和输出规范:

--- name: transcribe description: 对原始视频做语音转写,输出带时间戳的 JSON 结果。 --- # 素材分析与转写 ## 适用场景 - 需要知道视频素材里说了什么。 - 需要为后续剪辑生成带时间戳的文本依据。 ## 执行步骤 1. 用 ffprobe 读取素材基本参数。 2. 使用 faster-whisper 转写语音。 3. 将结果写入 work/transcript.json。 4. 将素材信息写入 work/materials.json。 ## 输出约束 - transcript.json 必须包含 segments 数组。 - 每个 segment 必须有 start、end、text 字段。 - 时间单位使用秒,保留 2 位小数。

SKILL.md 不写具体代码,而是告诉 Agent 执行规则。代码放在run.py,Agent 只需要调用脚本。

3.3 转写脚本实现

skills/transcribe/run.py核心逻辑:

import json import sys from pathlib import Path from faster_whisper import WhisperModel def probe_material(video_path: Path) -> dict: import subprocess cmd = [ "ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", str(video_path) ] result = subprocess.run(cmd, capture_output=True, text=True) return json.loads(result.stdout) def transcribe(video_path: Path, output_dir: Path) -> None: model = WhisperModel("small", device="cpu", compute_type="int8") segments, info = model.transcribe( str(video_path), language="zh", word_timestamps=False, vad_filter=True, ) transcript = {"segments": []} for seg in segments: transcript["segments"].append({ "start": round(seg.start, 2), "end": round(seg.end, 2), "text": seg.text.strip(), }) (output_dir / "transcript.json").write_text( json.dumps(transcript, ensure_ascii=False, indent=2), encoding="utf-8", ) if __name__ == "__main__": video_path = Path(sys.argv[1]) output_dir = Path(sys.argv[2]) output_dir.mkdir(parents=True, exist_ok=True) materials = probe_material(video_path) (output_dir / "materials.json").write_text( json.dumps(materials, ensure_ascii=False, indent=2), encoding="utf-8", ) transcribe(video_path, output_dir)

这里有几个关键点:

  • vad_filter=True可以过滤静音,减少无意义转写内容。
  • 中文素材建议显式传language="zh",不传也能自动识别,但有时会在开头混入少量英文误识别。
  • compute_type="int8"在 CPU 上更快,如果使用 GPU,可以换成float16

3.4 验证转写结果

运行命令:

cd ~/video-agent source .venv/bin/activate python skills/transcribe/run.py input/raw_1.mp4 work

正常输出是work/transcript.json。查看内容:

{ "segments": [ { "start": 0.82, "end": 4.16, "text": "今天我们来聊一个自动剪辑的完整方案" }, { "start": 4.32, "end": 8.25, "text": "这条视频会分为三个部分" } ] }

检查标准是:文本有没有明显漏字、时间戳是否连续、结尾时间是否和素材实际时长接近。如果时间戳整体偏移,可能是模型加载或音频采样导致,后面在第 7 节排查。

4. 第二个 Skill:自动生成剪辑脚本

4.1 从文本到剪辑决策

第二个 Skill 负责“决定剪哪里”。它读入转写文本,按规则选择保留片段。

剪辑规则可以很灵活,比如:

  • 开头 5 秒的无效寒暄删掉。
  • 包含“总结一下”的段落优先保留。
  • 单句时长超过 15 秒且没有停顿的片段降权。
  • 提前设置的总时长目标,超出的部分优先删语气词和重复表达。

规则越明确,输出越稳定。不要指望 Agent 凭感觉判断,需要用 JSON 把规则固化下来。

4.2 剪辑脚本 JSON 结构

edit_script.json的结构如下:

{ "version": 1, "source": "input/raw_1.mp4", "target_duration": 60, "clips": [ { "id": "clip_001", "start": 4.32, "end": 28.50, "reason": "核心观点介绍" }, { "id": "clip_002", "start": 34.10, "end": 76.40, "reason": "案例演示" } ], "order": ["clip_001", "clip_002"] }

clips是真正需要保留的时间片段,order是片段顺序。渲染器只认这个字段,不做任何剪辑决策。

4.3 生成逻辑与规则约束

在 Agent 环境下,SKILL.md 会要求模型读取transcript.jsonmaterials.json,按照规则生成 JSON。为了不依赖 Agent 也能演示,可以写一个本地规则脚本作为降级方案。

skills/script_builder/run.py的示例逻辑:

import json import sys from pathlib import Path def build_script(transcript_path: Path, materials_path: Path) -> dict: transcript = json.loads(transcript_path.read_text(encoding="utf-8")) materials = json.loads(materials_path.read_text(encoding="utf-8")) clips = [] for i, seg in enumerate(transcript["segments"]): text = seg["text"] duration = seg["end"] - seg["start"] # 规则1:删除过短且像语气词的内容 if duration < 1.2 and len(text) < 5: continue # 规则2:保留包含关键词的片段 if any(kw in text for kw in ["总结", "关键", "案例", "第一步"]): clips.append({ "id": f"clip_{i:03d}", "start": seg["start"], "end": seg["end"], "reason": "关键词命中", }) return { "version": 1, "source": materials.get("format", {}).get("filename", "input/raw_1.mp4"), "target_duration": 60, "clips": clips, "order": [c["id"] for c in clips], } if __name__ == "__main__": transcript_path = Path(sys.argv[1]) materials_path = Path(sys.argv[2]) output_path = Path(sys.argv[3]) script = build_script(transcript_path, materials_path) output_path.write_text( json.dumps(script, ensure_ascii=False, indent=2), encoding="utf-8", )

这里的规则脚本偏简单,但它证明了一条重要原则:剪辑脚本可以脱离模型单独生成。实际项目中,可以把“关键词命中”升级成大模型打分,也可以把“删除语气词”升级为文本分类,但数据结构不需要变。

4.4 验证剪辑脚本

运行:

python skills/script_builder/run.py work/transcript.json work/materials.json work/edit_script.json

检查生成的edit_script.json

  • 每个startend是否在素材时长范围内。
  • 片段之间是否有重叠,重叠会导致渲染结果重复。
  • order中的 id 是否都能在clips中找到。

如果片段过多,说明过滤规则太宽松;如果没有片段,说明关键词规则太严。这是调规则参数的地方。

5. 第三个 Skill:FFmpeg 自动执行与渲染

5.1 把剪辑脚本翻译成 FFmpeg 命令

第三个 Skill 不关心为什么这样剪,它只负责执行。核心任务是把edit_script.json翻译成 FFmpeg 命令。

最朴素的实现方式是逐段切片,再拼接:

ffmpeg -ss 4.32 -to 28.50 -i input/raw_1.mp4 -c copy work/clip_001.mp4 ffmpeg -ss 34.10 -to 76.40 -i input/raw_1.mp4 -c copy work/clip_002.mp4

再用 concat 协议或 filter 拼接。但直接-c copy在转场处容易出现时间戳错乱,所以更稳妥的方式是统一转成相同编码参数后再拼接。

5.2 渲染脚本实现

skills/renderer/run.py的核心逻辑:

import json import subprocess import sys from pathlib import Path def render(script_path: Path, output_path: Path) -> None: script = json.loads(script_path.read_text(encoding="utf-8")) source = script["source"] clips = {c["id"]: c for c in script["clips"]} part_files = [] for idx, clip_id in enumerate(script["order"]): clip = clips[clip_id] part_path = output_path.parent / f"part_{idx:02d}.mp4" part_files.append(part_path) cmd = [ "ffmpeg", "-y", "-ss", str(clip["start"]), "-to", str(clip["end"]), "-i", source, "-c:v", "libx264", "-preset", "veryfast", "-crf", "20", "-c:a", "aac", "-b:a", "192k", "-avoid_negative_ts", "make_zero", str(part_path), ] subprocess.run(cmd, check=True, capture_output=True, text=True) concat_file = output_path.parent / "concat.txt" concat_file.write_text( "\n".join(f"file '{p.name}'" for p in part_files), encoding="utf-8", ) merge_cmd = [ "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(concat_file), "-c", "copy", str(output_path), ] subprocess.run(merge_cmd, check=True, capture_output=True, text=True) if __name__ == "__main__": render(Path(sys.argv[1]), Path(sys.argv[2]))

这段脚本使用-c:v libx264 -preset veryfast -crf 20把每个片段统一转成 H.264,音频转成 AAC。最后用 concat 列表无损拼接。

5.3 关键参数说明

参数含义取值建议
-ss剪切起点设置为片段开始时间
-to剪切终点设置为片段结束时间
-crf画质控制,越小越清晰文件越大20 左右适合短视频分发
-preset veryfast编码速度与压缩率平衡自动化批量处理时用 veryfast
-avoid_negative_ts make_zero修正切片后时间戳偏移切片时建议加上
-c copy不重新编码直接复制流只适合同参数拼接阶段

-c copy能加快最终拼接速度,但前提是前面所有分片都使用完全一致的编码参数,否则拼接后可能出现音画不同步。

6. 三个 Skill 串联运行:从原始视频到成片

6.1 串联方式

3 个 Skill 可以通过一个简单的 Shell 脚本串联。把输入素材放到input/后,依次执行:

cd ~/video-agent source .venv/bin/activate python skills/transcribe/run.py input/raw_1.mp4 work python skills/script_builder/run.py work/transcript.json work/materials.json work/edit_script.json python skills/renderer/run.py work/edit_script.json output/final.mp4

看起来只是三行命令,但每一步之间都必须检查上一步输出成功后再继续。实际工程中建议写一个pipeline.sh,并在每步之间检查退出码:

set -e python skills/transcribe/run.py input/raw_1.mp4 work || exit 1 python skills/script_builder/run.py work/transcript.json work/materials.json work/edit_script.json || exit 1 python skills/renderer/run.py work/edit_script.json output/final.mp4 || exit 1

set -e的作用是遇到错误立即退出,避免带着坏中间产物继续跑。

6.2 完整运行示例

假设原始素材时长 120 秒,目标剪辑出 60 秒成片。转写后,脚本生成两个片段,渲染器输出final.mp4

运行日志:

[transcribe] 已转写 32 条片段 [script_builder] 已生成 2 个剪辑片段 [renderer] 已生成 output/final.mp4

正常结果是一个时长约 60 秒、音画同步、内容连续的 MP4 文件。

6.3 验证成片质量

使用 ffprobe 检查成片信息:

ffprobe -v quiet -print_format json -show_format output/final.mp4

检查字段:

  • duration是否接近目标时长。
  • bit_rate是否在合理范围。
  • 播放时重点听片段交界处是否有爆音、画面是否卡顿。

如果成片时长和目标时长差距很大,大概率是剪辑脚本生成的片段过短或过多,回到第 4 节调整规则。

7. 常见问题与排查路径

7.1 转写结果不准、时间戳偏移

现象:字幕内容和语音对不上,或者每句的起点整体提前。

可能原因:

  • 模型选择过小。
  • 没有开启静音过滤。
  • 视频本身有背景音乐或多人说话。

排查方式:

  • smallmedium模型试跑一段。
  • 对比语音开头和首句时间戳之间的差值。
  • 检查视频是否在录音阶段就存在音频延迟。
问题现象常见原因检查方式处理建议
文本错别字多模型过小换更大模型对比使用 small/medium,必要时开启initial_prompt
时间戳整体偏移音频流采样率问题用 ffprobe 查看音频参数先用 ffmpeg 统一重采样到 16kHz
静音内容被转写没有开 VAD检查 segment 是否过多开启vad_filter=True

7.2 渲染后音画不同步

现象:画面正常,但声音比画面慢或快。

排查顺序:

  1. 检查-ss放在-i前还是后。放前面可以快速定位到关键帧,但某些输入格式会丢帧;放后面更精确,但速度慢。
  2. 检查分片阶段是否所有片段统一编码。
  3. 检查最终 concat 阶段是否使用了-c copy,如果分片参数不一致,这里最容易出问题。

推荐做法是切片阶段统一转码,拼接阶段才用-c copy。不要在生产流程中使用-c copy做切片,除非确认源文件关键帧结构完全一致。

7.3 Agent 没有正确加载 Skill

现象:调用 3 个 Skill 时,Agent 总是自己乱写命令,不读 SKILL.md。

常见原因:

  • SKILL.md 放错了目录。
  • Skill 描述不明确,Agent 没有识别到适用场景。
  • 项目目录没有按约定设置。

排查方式:

  • 在 Agent 工作目录下执行/skills或对应当前工具的 skill 列表命令,确认 Skill 是否被加载。
  • 打开 SKILL.md,检查 frontmatter 里的namedescription是否清晰。
  • 直接把 SKILL.md 中的描述改成“当用户要求处理原始视频并生成剪辑脚本时,必须使用本 Skill”。

7.4 FFmpeg 找不到编码器

现象:

Unknown encoder 'libx264'

可能原因:FFmpeg 版本较老,或者安装时没有包含 H.264 编码器。

检查方式:

ffmpeg -encoders | grep 264

处理建议:

  • Ubuntu 重新安装:sudo apt install ffmpeg
  • macOS 重新安装:brew install ffmpeg
  • 如果必须使用当前版本,可以改用mpeg4编码器,但兼容性不如 H.264,只适合本地测试。

8. 生产环境落地建议

8.1 学习环境与生产环境的差异

跑通演示和真正上线是两回事。

维度学习/演示环境生产环境
素材来源本地固定文件上传队列、对象存储
任务触发手动执行脚本任务队列、事件触发
转写模型本地 CPU int8GPU 或多实例并发
日志print 输出结构化日志、任务 ID 关联
异常处理脚本失败即停重试、告警、人工兜底
安全单人本机权限隔离、素材访问控制

生产环境至少还要考虑:一次转写可能消耗大量 CPU,需要限制并发;FFmpeg 渲染是长耗时任务,需要记录每个任务的状态,避免重复渲染;素材和成片都要有备份和清理策略。

8.2 可复用检查清单

跑通本项目或部署到生产前,按下面清单检查:

  • [ ]ffmpegffprobe是否可用。
  • [ ] Python 虚拟环境是否激活,依赖是否安装完成。
  • [ ] 输入素材是否存在,命名是否符合规范。
  • [ ] 3 个 Skill 的目录路径是否完整。
  • [ ] SKILL.md 中的输出路径是否与脚本一致。
  • [ ] 转写结果中是否包含segments
  • [ ] 剪辑脚本中的时间戳是否都在素材时长范围内。
  • [ ] 片段之间是否有重叠。
  • [ ] 渲染前是否确认编码器可用。
  • [ ] 成片播放检查音画同步和转场。

8.3 扩展方向

跑通 3 个 Skill 之后,可以继续扩展:

  • 字幕压制:在 renderer 中增加subtitlesfilter,把转写文本自动压成视频字幕。
  • 多素材拼接:让 script_builder 支持多个 sources,输出结构增加source字段。
  • 镜头级剪辑:用镜头检测算法找到视频切帧点,再结合转写文本,实现“按句+按镜头”双维度剪辑。
  • 审核流程:在 script_builder 和 renderer 之间增加一个人工审核环节,只审核 JSON,不处理视频,效率会比重新剪辑高很多。

自动化剪辑真正的价值,不是完全取代剪辑师,而是把“理解素材”和“执行操作”变成标准化流程。Skill 是这套流程最好的载体:每个能力独立维护、独立测试,组合起来就是一条完整生产线。

如果只记住一条经验,我的建议是:先把剪辑决策和剪辑执行彻底分开。转写只负责生成文本,剪辑脚本只负责“决定剪哪里”,渲染只负责“执行命令”。这样 3 个 Skill 各自职责清晰,整个系统才可能稳定跑通。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 13:21:50

MOS管反向倒灌:关断后为何还有电压?体二极管深度解析

面试官把一张原理图推到你面前&#xff1a;“这个负载开关&#xff0c;我已经在程序里把栅极拉到高电平了&#xff0c;为什么输出端还能量到电压&#xff1f;”这不是段子。很多硬件工程师都在面试或实际调试中踩过这个坑。有人答“栅极没拉干净”&#xff0c;有人答“MOS管漏电…

作者头像 李华
网站建设 2026/8/31 13:20:38

基于Qt与C++的TCP网络通信框架:从设计到联调全解析

简介&#xff1a;本资源是一套基于Qt框架与C语言实现的完整TCP网络通信示例程序&#xff0c;面向计算机科学、信息安全、物联网、人工智能等专业的在校学生及初学者&#xff0c;用于支撑毕业设计、课程设计、期末大作业等实践教学场景。项目包含功能完备的客户端与服务端双模块…

作者头像 李华
网站建设 2026/8/31 13:16:53

小红书数据采集实战:Python爬虫与反爬绕过全攻略

简介&#xff1a;本资源是一套完整可用的小红书平台Python爬虫源码&#xff0c;面向计算机专业本科生及入门级爬虫开发者&#xff0c;适用于毕业设计、课程实践与数据采集技术学习。项目包含1080个文件&#xff0c;以781个JavaScript文件&#xff08;支撑前端交互与自动化逻辑&…

作者头像 李华
网站建设 2026/8/31 13:16:48

Django文档管理系统源码解析:从权限控制到Nginx部署实战

简介&#xff1a;这是一套基于Python Django框架开发的文档管理系统完整源码&#xff0c;面向Web开发初学者与Django进阶学习者&#xff0c;解决企业或团队中常见的文档上传、分类存储、权限管控与在线检索等核心管理需求。压缩包共64个文件&#xff0c;包含15个Python后端逻辑…

作者头像 李华
网站建设 2026/8/31 13:15:29

MinIO被fork成Silo:对象存储许可证与治理的博弈

最近对象存储圈子里最值得关注的一则消息&#xff0c;是 MinIO 被社区 fork 成了新项目 Silo。这件事表面上是一次“代码分叉”&#xff0c;但背后真正值得琢磨的&#xff0c;是它折射出的许可证、项目治理和商业化边界问题。如果你所在团队正在用 MinIO 做自建对象存储&#x…

作者头像 李华