
这次我们来看一个更落地的 AI 应用把视频自动化剪辑拆成 3 个 Skill跑通从长视频到成片的全流程。所谓 Skill是 Claude Code、Codex、opencode 这批 AI 编程工具里流行起来的能力封装方式一个 SKILL.md 描述职责和调用方式scripts 目录放可执行脚本resources 目录放字体、模板等资源。AI 在对话中根据描述自动调用脚本而不是让用户手敲一长串 ffmpeg 命令。这套方案的价值在于剪辑这件事不再是“人写死一个 Python 脚本”而是变成三个可被 AI 调用的能力单元素材分析与粗剪、字幕生成与自动包装、批量导出与发布清单。三个 Skill 各自独立又能串成一条流水线。我先说结论流程跑通后把一个 1 小时直播录屏交给 Agent它能自动输出若干短视频片段、SRT 字幕、烧录字幕后的成片以及一份可直接粘贴的发布说明。整条链路以本地处理为主既能接批量任务也能封一层 HTTP API 给其他系统调用。这篇文章会给出三个 Skill 的目录结构、SKILL.md、核心脚本、批量任务示例和 API 封装思路同时把实际调试里容易踩的坑整理成排查表。适合三类读者想用 AI Agent 减少重复剪辑工作的自媒体运营负责视频素材初筛的剪辑师以及正在研究 Skill 怎么落地的 AI 应用开发者。如果你以为这是某个一键生成视频的在线工具那不是这篇文章的方向如果你想在本地搭一套可扩展的自动化剪辑管线这篇可以直接收藏。文章里的命令、脚本都会保留可运行的最小版本。具体模型名称、目录名称、服务端口在不同机器上会有差异复制时注意替换。所有素材只建议使用自己拍摄、已获授权或有明确使用许可的视频。1. 核心能力速览先把三个 Skill 的整体规格列出来方便快速判断是否符合你的需求。能力项说明项目类型AI Agent Skill 工作流封装面向视频自动化剪辑核心功能视频素材分析、静音/场景粗剪、字幕生成与烧录、批量转码、发布清单生成Skill 拆分clip-cutter、sub-master、release-pack 三个独立 Skill运行方式命令行脚本为主AI Agent 按 SKILL.md 描述自动调用依赖组件Python 3.10、ffmpeg、faster-whisper / openai-whisper、可选 FastAPI硬件门槛ffmpeg 流程 CPU 可跑语音转写用 CPU 也能出结果有 GPU 会更快批量任务支持可通过 shell 循环或任务队列批量处理API 能力可封装为本地 HTTP 服务便于接入已有系统输出结果粗剪片段、SRT 字幕、烧录字幕后的 MP4、封面、发布说明合规要求只处理已授权素材涉及肖像、音乐、版权内容需提前确认授权我没有把显存占用写死因为语音转写模型从 tiny 到 large 差异很大而且 CPU/GPU 推理差异也明显。首次使用建议先拿一小段视频验证再决定用哪个模型。2. Skill 机制与自动化剪辑的组合方式Skill 的底层逻辑并不复杂。它把一个能力单元拆成三部分说明文件、执行脚本、资源文件。说明文件告诉 AI“这个 Skill 能做什么、参数是什么、输出放哪里”执行脚本负责真正调用 ffmpeg、whisper 等工具完成计算资源文件用于放置中文字体、模板、默认配置。AI 不需要懂 ffmpeg 的每个参数它只需要读懂 SKILL.md把用户需求映射成脚本参数再执行脚本并检查结果。放到剪辑场景里这个机制非常适合。视频剪辑流程天然要处理文件系统、执行外部命令、等待长任务这些都不是大模型在纯对话里擅长的事。你让 AI 在对话里“帮我剪掉前 3 秒”它能编一个合理命令但在多文件、多步骤、批量场景里容易出错。Skill 把标准操作固化成脚本AI 只负责决策和编排稳定性和可复用性都上来了。为什么拆成三个而不是一个大 Skill因为视频生产链路的三个阶段差异很大粗剪关注内容结构字幕关注语音转写准确性导出关注编码参数和平台规格。拆开后可以单独测试、单独替换。比如不想用 whisper就把 sub-master 内部的转写脚本换成本地语音识别引擎不影响另外两个 Skill。AI 编排时也能组合使用先让 clip-cutter 出切片再让 sub-master 对切片统一加字幕最后用 release-pack 按平台导出。这种“AI 编排 脚本执行”的模式等于把一条剪辑 SOP 沉到了代码里。你沉淀的是工作流本身而不只是某一个视频的结果。下次换一批素材只要素材结构一致Skill 可以直接复用。3. 适用场景与合规边界先说适合干什么。第一类是直播录屏和课程视频的高光切片。长时间视频里往往有大量沉默、重复、寒暄片段静音检测能自动找到可切割位置把有效内容切成若干短视频。第二类是采访或口播视频的二次加工。长访谈转成多个主题短视频是自媒体常见的需求AI 可以根据转写文本划分主题再调用粗剪脚本切出对应片段。第三类是素材初筛。剪辑师拿到大量原始素材后先用 Skill 抽出场景列表和关键帧不用把每个视频完整看一遍。第四类是批量格式转换与发布准备。一批横屏视频要统一转成竖屏、加字幕、重命名这类机械任务非常适合脚本批量跑。不合适的场景也要说清楚。真正需要创意和节奏感的精剪比如卡点混剪、剧情向剪辑、复杂转场设计Skill 很难替代人工判断。它擅长的是“按规则切、按文本配字幕、按规格导出”不是“理解导演意图”。另外如果视频里包含大量需要人工确认的信息误读风险高的内容也不要盲目自动化。合规是硬边界。自动化剪辑不改变素材来源的授权性质自己没有拍摄、没有获得授权、平台明确禁止搬运的内容换任何工具都不应该碰。涉及人脸的肖像授权、背景音乐的版权、商品商标的露出都要在跑量之前确认清楚。批量生成的视频如果要发布到多个平台还要逐条核对平台规则比如水印、时长、竖屏比例、违禁词。这里多花 10 分钟比批量发布后被下架、限流、投诉的代价小得多。4. 环境准备与 Skill 目录结构环境准备不需要很复杂。操作系统建议 Linux 或 macOS命令脚本差异小Windows 用户可以用 WSL或者在 PowerShell 中调整路径分隔符。Python 版本用 3.10 以上避免某些库版本兼容问题。必须先装好 ffmpeg并把可执行文件加入 PATH。Whisper 转写这块我习惯用 faster-whisper它对 CPU 和 GPU 都支持按实际机器选择合适的 compute_type 就行。# Debian / Ubuntu sudo apt update sudo apt install -y ffmpeg python3-pip # macOS brew install ffmpeg # Python 依赖 pip install faster-whisperSkill 的放置目录主流做法是放在用户级或项目级配置目录。以 Claude Code 风格为例用户级 Skill 放在~/.claude/skills/项目级 Skill 放在.claude/skills/Codex、opencode 等工具也有类似机制具体路径以工具文档为准。每个 Skill 是一个独立目录。skills/ ├── clip-cutter/ │ ├── SKILL.md │ ├── scripts/ │ │ ├── detect_scenes.py │ │ └── cut_clips.py │ └── resources/ │ ├── example_params.json │ └── prompt_templates/ ├── sub-master/ │ ├── SKILL.md │ ├── scripts/ │ │ ├── transcribe.py │ │ └── burn_subtitle.py │ └── resources/ │ ├── fonts/ │ └── subtitle_style.conf └── release-pack/ ├── SKILL.md ├── scripts/ │ ├── export_by_profile.py │ └── build_publish_notes.py └── resources/ ├── profiles/ └── cover_templates/目录结构本身也是约定的一部分。AI 通过 SKILL.md 找到脚本路径脚本通过固定的输入输出目录读取素材、写入结果。建议约定每个 Skill 的输入目录统一为input/或通过参数传入输出统一写到output/临时文件放temp/这样后续接批量任务时不容易乱。5. 三个 Skill 的落地实现这一章是重点按 clip-cutter、sub-master、release-pack 三个 Skill 分别展开每个都给出 SKILL.md 示例、核心脚本思路和验证方式。5.1 Skill 1素材分析与粗剪第一个 Skill 解决的是“一个长视频哪里可以切开”。我选择的基础策略是静音检测加场景切分。静音检测用来找“没有人说话”的间隙适合口播和直播录屏场景切分用来找画面突变位置适合多机位素材混剪。两个结果合并成一批候选切点再由粗剪脚本输出片段。SKILL.md 的职责描述要尽量具体。AI 需要知道这个 Skill 的输入是什么、输出是什么、适合什么素材这样才不会在对话中错误调用。--- name: clip-cutter description: 对长视频做静音检测和场景切分输出候选剪辑片段。输入为视频文件路径输出为 JSON 切点文件和 MP4 粗剪片段。 version: 1.0.0 --- # clip-cutter 负责把长视频切成短视频素材。流程 1. 用 ffmpeg silencedetect 检测静音区间 2. 用 ffmpeg scene 检测场景切换点 3. 合并候选切点按最短时长过滤 4. 输出切点 JSON 和粗剪片段到 output 目录这里字段写法是通用格式实际使用的工具可能在 frontmatter 里要求name、description、allowed-tools等不同字段。原则是“description 越具体AI 调用越准确”。核心脚本可以用 Python 调用 ffmpeg解析 stderr 里的静音信息。ffmpeg 的 silencedetect 输出形如silence_start: 12.34和silence_end: 15.67 | silence_duration: 3.33Python 用正则解析即可。import json import re import subprocess from pathlib import Path def detect_silence(video_path: str, noise: str -30dB, duration: str 0.8): cmd [ ffmpeg, -i, video_path, -af, fsilencedetectnoise{noise}:d{duration}, -f, null, - ] result subprocess.run(cmd, capture_outputTrue, textTrue) log result.stderr silences [] for start, end in zip( re.findall(rsilence_start: ([\d.]), log), re.findall(rsilence_end: ([\d.]), log), ): silences.append({start: float(start), end: float(end)}) return silences if __name__ __main__: video Path(__file__).resolve().parent.parent.parent / input / demo.mp4 silences detect_silence(str(video)) output_path Path(__file__).resolve().parent.parent.parent / output / silence.json output_path.parent.mkdir(parentsTrue, exist_okTrue) output_path.write_text(json.dumps(silences, ensure_asciiFalse, indent2), encodingutf-8) print(fdetected {len(silences)} silence segments - {output_path})这个脚本是最小版。实际使用时我会在 detect_scenes.py 里再加一个 scene 检测把结果 merge再用最短片段时长过滤。粗剪时根据切点列表调用ffmpeg -ss START -to END -i input.mp4 -c copy output.mp4注意用-ss放在-i之前是快速 seek 模式能减少解码开销。验证方法很简单拿一段 3 到 5 分钟的口播视频放进去看 output 目录是否出现silence.json再用 ffprobe 检查切片时长是否符合预期。如果切出来的片段里前 0.5 秒有杂物可以把每个切点前后偏移一定时长先设置pre_roll和post_roll两个参数默认 0.3 秒灵活调整。5.2 Skill 2字幕生成与自动包装第二个 Skill 解决的是“片段有了字幕怎么自动生成、怎么烧进去”。我选择 faster-whisper 作为转写引擎因为它对 CPU 推理的支持比较友好不需要在显存上纠结。模型可以从 tiny、small、medium 里选先拿 1 分钟音频测测准确率和速度再决定大批量用哪个。transcribe.py 的核心逻辑是加载模型、读入视频或音频、推理得到带时间戳的文本段、写入 SRT。import sys from pathlib import Path from faster_whisper import WhisperModel def transcribe_to_srt(video_path: str, srt_path: str, model_size: str small): model WhisperModel(model_size, devicecpu, compute_typeint8) segments, info model.transcribe(video_path, languagezh, vad_filterTrue) lines [] for idx, segment in enumerate(segments, start1): start format_timestamp(segment.start) end format_timestamp(segment.end) lines.append(f{idx}\n{start} -- {end}\n{segment.text.strip()}\n) Path(srt_path).write_text(\n.join(lines), encodingutf-8) def format_timestamp(seconds: float) - str: ms int(round(seconds * 1000)) h, ms divmod(ms, 3600000) m, ms divmod(ms, 60000) s, ms divmod(ms, 1000) return f{h:02}:{m:02}:{s:02},{ms:03} if __name__ __main__: video sys.argv[1] srt sys.argv[2] transcribe_to_srt(video, s