☰
AI自动化剪辑:三个Skill打造从长视频到成片的流水线
2026/10/26 22:19:40 网站建设 项目流程

一条短视频,从拿到原始素材到发布,通常要经历粗剪、去废片段、加字幕、挑高光、配乐、转场、导出这几个环节。如果你只是偶尔剪一条 vlog,用剪映、Premiere 手动拖一拖也能接受;但如果你每周要处理几条长访谈、课程回放、直播切片,就会明显感觉到:真正耗时间的不是“剪辑操作”,而是反复在时间轴上做判断——哪些片段值得留,哪几句话信息密度最高,哪里该切一刀。

我用 AI 编程助手的方式做自动化剪辑,把整个流程拆成了 3 个 Skill,并且已经跑通了一套从“长视频输入”到“成片输出”的流水线。

先说判断:AI 自动化剪辑的关键,不是让 AI 帮你点按钮,而是把剪辑师脑子里的判断规则,变成一套可以复用、可以调试、可以逐步调优的 Skill。

这篇文章我会先解释 Skill 到底是什么、为什么它比普通提示词更适合做剪辑流水线,然后把 3 个 Skill 的设计思路、代码实现、运行验证、常见坑逐一拆开讲。读完你可以直接照着一套最小实现跑通自己的自动化剪辑流程。

1. 为什么是 Skill,而不是“AI 一键成片”

市面上已经有不少“AI 一键成片”工具,输入一段文字描述就能生成视频。这类工具在营销素材、快剪场景下确实有用,但它有两个问题:素材内容是模型生成的,不是你真实拍摄的;成片风格由平台模板决定,很难针对你自己的节目形态做精细调整。

如果你要剪的是真实拍摄的课程、访谈、直播回放,需要的是另一类工具:一个能听懂“帮我保留老板讲核心观点的部分,去掉寒暄”、能自动调用剪辑命令、能按固定节奏输出成片的自动化框架。

这就是 Skill 的用武之地。

Skill 可以类比为“用户态插件”。它是结构化文件加脚本的集合,包含三个核心部分:

  • 描述文件:告诉 AI 这个 Skill 在什么场景下使用、能解决什么问题。
  • 工作流提示词:把剪辑中需要连续执行的步骤写成到位的指令,让 AI 按照固定顺序处理任务。
  • 工具脚本:真正去调用 ffmpeg、语音识别、字幕导出、视频拼接等命令,把 AI 的“裁剪意图”变成真实文件操作。

普通提示词是“一次性对话”,Skill 是“可复用流程”。普通提示词给不出稳定的工具调用逻辑,Skill 可以像函数一样被随时调用。对视频剪辑这种“流程长、步骤多、重复性高”的场景,Skill 的优势非常明显:它把剪辑经验沉淀成了代码,而不是留在某次对话上下文里。

2. 自动化剪辑流水线的整体设计

我跑通的 3 个 Skill,正好对应剪辑三个阶段:

阶段Skill 名称主要职责输入输出
第一阶段粗剪切分长视频去头尾、删除静音和明显废片段、按场景切分原始长视频带时间戳的分段片段列表
第二阶段字幕与高光语音转写、字幕生成、根据关键词和语义密度提取高光片段分段片段列表SRT 字幕、高光片段列表
第三阶段成片合成按高光片段排序拼接、添加转场、自动配乐、统一导出格式高光片段列表最终成片文件

用流程表达就是:

原始视频 -> Skill 1 粗剪切分 -> 分段片段 -> Skill 2 字幕与高光 -> 高光列表 | v 最终成片 <- Skill 3 成片合成 <- 高光片段文件 <------------------------+

这样的拆法有一个很重要的理由:每个 Skill 只完成一件事,输入输出都是标准文件,所以中间任何一步出错都可以单独排查、单独重跑。剪辑行业多年的工程经验也是这样收敛的:先做素材整理,再做内容理解,最后才做包装合成。

如果你一开始就想写一个“全自动剪好一条视频”的大脚本,大概率会陷入一个极其长的 if-else 泥潭。把流程拆成 Skill,本质上是把复杂度分摊到了不同的边界里。

3. 环境准备与 Skill 项目结构

这套 Skill 方案的运行环境并不复杂,核心依赖是 ffmpeg 和 Python。ffmpeg 负责视频处理,Python 负责编排和调用本地工具,AI 编程助手负责理解需求并调度 Skill。

我建议的最小环境如下:

依赖说明版本建议
操作系统macOS / Linux / Windows WSL以实际项目为准
ffmpeg视频剪切、拼接、转码建议使用较新的稳定版
Python脚本编排3.9 以上
语音识别工具本地 Whisper 或云端 ASR 接口以实际项目为准

以我使用的 AI 编程助手(支持 Skill 机制的工具)为例,每个 Skill 是一个独立的目录,结构如下:

skills/ ├── rough-cut/ │ ├── SKILL.md │ └── scripts/ │ ├── split_scenes.py │ └── cut_fragments.sh ├── subtitle-highlight/ │ ├── SKILL.md │ └── scripts/ │ ├── transcribe.py │ └── extract_highlights.py └── final-mix/ ├── SKILL.md └── scripts/ ├── concat_clips.py └── export_final.sh

SKILL.md 是这个 Skill 的说明书,AI 会先读它理解职责,再去调用 scripts 里的脚本。整个目录挂到你的 AI 编程助手工作区之后,AI 就可以在对话中识别当前任务并自动加载对应 Skill。

4. Skill 1:粗剪切分——把长视频变成可用片段

第一个 Skill 解决的是“素材太长”的问题。一段两小时的直播回放,如果直接全部转写、全部保留,后面的处理压力会非常大。粗剪的目标不是做精细剪辑,而是快速去重、去静音、做场景切分,产出一份 m3u8 级别的片段清单。

这里最容易踩的坑是:很多同学直接用 ffmpeg 按固定时长切分,比如每 10 分钟一刀。这种切法切出来的片段完全不顾内容语义,后面挑高光的时候会非常痛苦。更好的切法是做“场景检测”,在画面切换明显的地方切一刀,这样每个片段内容相对完整。

我设计的粗剪 Skill 模块,核心流程如下:

  • 用 ffmpeg 的 silencedetect 检测静音段,把静音超过 3 秒的位置标记出来,这些位置是自然断点。
  • 用 scene detection 计算画面差异,在差异超过阈值的位置生成切点。
  • 合并两部分切点,生成一个带时间戳的片段列表。
  • 输出 JSON 文件,供下一个 Skill 读取。

SKILL.md 的核心描述如下:

# 粗剪切分 将输入的长视频按照静音检测和场景检测结果切成多个片段, 输出片段时间戳列表 JSON 文件。 使用场景: - 视频文件时长超过 20 分钟 - 需要先整理素材再进入高光提取 - 需要去除明显静音和头尾无意义内容 依赖命令: - ffmpeg - python3 输出文件: - segments.json(片段列表)

scripts/split_scenes.py 是核心实现,用 Python 调用 ffmpeg 完成切分:

#!/usr/bin/env python3 # 文件路径:skills/rough-cut/scripts/split_scenes.py import json import subprocess import sys def run_cmd(cmd): """执行命令并返回 stdout 文本""" result = subprocess.run(cmd, shell=True, capture_output=True, text=True) if result.returncode != 0: print(f"命令执行失败: {cmd}\n{result.stderr}") sys.exit(1) return result.stdout def detect_silence(input_file, threshold=-30, min_duration=3.0): """检测静音区间""" cmd = ( f'ffmpeg -i "{input_file}" -af ' f'"silencedetect=noise={threshold}dB:d={min_duration}" ' f'-f null - 2>&1' ) output = run_cmd(cmd) silences = [] for line in output.splitlines(): if "silence_start" in line: start = float(line.split("silence_start: ")[1]) silences.append({"start": start, "end": None}) elif "silence_end" in line and silences: end = float(line.split("silence_end: ")[1]) silences[-1]["end"] = end return [s for s in silences if s["end"] is not None] def detect_scenes(input_file, threshold=0.3): """检测场景切换点""" cmd = ( f'ffmpeg -i "{input_file}" -filter:v ' f'"select=\'gt(scene,{threshold})\',showinfo" ' f'-f null - 2>&1' ) output = run_cmd(cmd) scenes = [] for line in output.splitlines(): if "pts_time:" in line: pts = line.split("pts_time:")[1].split()[0] scenes.append(float(pts)) return scenes def merge_cut_points(silences, scenes, video_duration): """把静音和场景检测得到的切点合并排序""" cut_points = [0.0, video_duration] for s in silences: mid = (s["start"] + s["end"]) / 2 cut_points.append(mid) for scene in scenes: cut_points.append(scene) cut_points = sorted(set(round(p, 2) for p in cut_points)) return cut_points if __name__ == "__main__": input_file = sys.argv[1] # 获取视频时长,用于构造最后一段 duration_cmd = f'ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "{input_file}"' video_duration = float(run_cmd(duration_cmd).strip()) silences = detect_silence(input_file) scenes = detect_scenes(input_file) cut_points = merge_cut_points(silences, scenes, video_duration) segments = [] for i in range(len(cut_points) - 1): start = cut_points[i] end = cut_points[i + 1] if end - start < 5: continue # 过滤掉太短的片段 segments.append({"index": len(segments), "start": start, "end": end}) with open("segments.json", "w", encoding="utf-8") as f: json.dump({"segments": segments, "source_file": input_file}, f, ensure_ascii=False, indent=2) print(f"完成:共生成 {len(segments)} 个片段")

这里做了两件关键的事:一是用静音中点作为自然断点,避免切在说话中间;二是过滤掉时长不足 5 秒的片段,避免出现大量碎片。

运行方式:

cd skills/rough-cut python3 scripts/split_scenes.py /path/to/input.mp4

成功运行后,会在当前目录生成 segments.json。如果运行失败,先看 ffmpeg 是否在 PATH 中,再看输入文件路径是否有空格导致参数解析错误。

5. Skill 2:字幕与高光提取——让 AI 理解视频内容

粗剪完成之后,素材仍然是“一堆片段”,AI 还不知道每一段在讲什么。第二个 Skill 的目标是把片段转成文字,再用文字内容做判断,挑出高光片段。

这个环节是整个流程里最像“AI 剪辑师”的一步。我的做法分两步:先做语音转写,生成每段片段的文本和字幕;再用规则和 AI 结合的方式提取高光。

语音转写推荐用本地 Whisper 或者任意 ASR 接口。如果是本地运行,转写命令类似:

whisper /path/to/segment.mp4 --language zh --task transcribe --output_format srt

这条命令成功后会生成同名的 .srt 文件。需要注意,转写是耗时操作,视频越长越慢。如果素材很多,建议先用 GPU 或者控制并行任务数量,避免把机器跑死。

拿到各片段的文本之后,高光提取就有依据了。我借鉴了一个很小的策略:把文本按句子切成单元,给句子打分。分数来源有三部分:

  • 关键词命中:标题、摘要里的关键词,视频的节目主题词,以及“重点、核心、结论、最后、总结”这类高信息密度词。
  • 语义密度:句子长度和数字序号等结构特征。
  • 情感强度:语气词、重复词、加强语气的词汇。

这个打分逻辑放在 extract_highlights.py 里,可以灵活调整策略。核心代码如下:

#!/usr/bin/env python3 # 文件路径:skills/subtitle-highlight/scripts/extract_highlights.py import json import sys import re # 配置区:可自行调整关键词 KEYWORDS = ["核心", "结论", "重点", "注意", "总结", "关键"] STRUCTURE_MARKS = ["第一", "第二", "第三", "首先", "然后", "最后", "一方面", "另一方面"] EMOTION_WORDS = ["非常", "特别", "极其", "十分", "很明显", "毋庸置疑"] def load_srt(srt_path): """解析 SRT 字幕文件为句子列表""" with open(srt_path, "r", encoding="utf-8") as f: content = f.read() blocks = re.split(r"\n\s*\n", content.strip()) sentences = [] for block in blocks: lines = block.strip().split("\n") if len(lines) < 2: continue # 第一行是序号,第二行是时间轴,后面的行是文本 text = " ".join(lines[2:]).strip() if not text: continue sentences.append({"text": text}) return sentences def score_sentence(text): """给句子打高光分数""" score = 0 for kw in KEYWORDS: if kw in text: score += 5 for mark in STRUCTURE_MARKS: if mark in text: score += 3 for word in EMOTION_WORDS: if word in text: score += 2 # 句子越长,往往信息量越大;但过长也可能是废话连篇 if 30 <= len(text) <= 120: score += 2 return score def extract_highlights(segments_json, srt_dir, top_n=10): with open(segments_json, "r", encoding="utf-8") as f: data = json.load(f) segment_scores = [] for seg in data["segments"]: srt_file = f"{srt_dir}/segment_{seg['index']:03d}.srt" try: sentences = load_srt(srt_file) except FileNotFoundError: continue total_score = sum(score_sentence(s["text"]) for s in sentences) if sentences: total_score += min(len(sentences) * 0.5, 5) # 鼓励信息密度适中的片段 segment_scores.append({ "index": seg["index"], "start": seg["start"], "end": seg["end"], "score": round(total_score, 2), "text_preview": "".join(s["text"] for s in sentences[:3]) }) segment_scores.sort(key=lambda x: x["score"], reverse=True) return segment_scores[:top_n] if __name__ == "__main__": segments_json = sys.argv[1] srt_dir = sys.argv[2] output_json = sys.argv[3] if len(sys.argv) > 3 else "highlights.json" top_n = int(sys.argv[4]) if len(sys.argv) > 4 else 10 highlights = extract_highlights(segments_json, srt_dir, top_n) with open(output_json, "w", encoding="utf-8") as f: json.dump({"highlights": highlights}, f, ensure_ascii=False, indent=2) print(f"完成:共提取 {len(highlights)} 个高光片段") for h in highlights: print(f" 片段 {h['index']:03d} 分数 {h['score']:.2f}:{h['text_preview'][:40]}")

运行命令:

cd skills/subtitle-highlight python3 scripts/extract_highlights.py ../rough-cut/segments.json ./srt_files highlights.json 10

这个脚本的核心是分数可解释。当你发现某个片段被错误选入高光时,可以直接看它的文本和分数构成,调整关键词或权重即可,不需要重写整个流程。这一步是 Skill 方案优于纯提示词方案的关键:规则是代码,可测试、可版本化管理。

6. Skill 3:成片合成——拼接、转场与导出

高光片段确定之后,最后一步是把这些片段拼成一个完整成片。这个 Skill 看起来最“机械化”,但反而是最容易出问题的环节,因为 ffmpeg 的拼接和转码参数一旦设置错误,轻则画面黑屏,重则整条视频导出失败。

我的成片合成 Skill 分成两步:

第一步,把高光片段从原视频里真正裁剪出来,生成独立的小片段文件。裁剪时要注意,ffmpeg 的-ss和-i的顺序有讲究。-ss放在-i前面是快速跳转关键帧,速度快但可能不精确;放在-i后面是逐帧解码,精度高但慢。对最终成片来说,建议用后者,宁可慢一点也要保证不出现画面跳动。

第二步,把裁剪出来的小片段按顺序拼接。ffmpeg 有 concat filter 和 concat demuxer 两种方式。我推荐用 concat demuxer,因为它不需要重新编码,拼接速度快,质量无损。

concat 拼接需要一个列表文件:

# 文件路径:skills/final-mix/concat_list.txt file 'clips/highlight_001.mp4' file 'clips/highlight_002.mp4' file 'clips/highlight_003.mp4'

然后执行拼接命令:

ffmpeg -f concat -safe 0 -i concat_list.txt -c copy final_no_audio.mp4

这里-c copy表示不重新编码,直接复制音视频流。但这里有一个坑:如果裁剪出的多个片段编码参数不一致,-c copy可能失败。为了稳妥,可以在裁剪的时候就统一转成相同编码,或者在拼接失败时去掉-c copy重新编码。

完成基础拼接后,我会根据预设模板给成片加上一个简单的开头标题和片尾,再统一导出为 1080p、H.264 编码的 MP4,方便直接上传到视频平台。这个逻辑封装在 export_final.sh 中:

#!/usr/bin/env bash # 文件路径:skills/final-mix/scripts/export_final.sh set -e INPUT_FILE="$1" OUTPUT_FILE="$2" ffmpeg -y -i "$INPUT_FILE" \ -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" \ -c:v libx264 -preset medium -crf 20 \ -c:a aac -b:a 192k \ -movflags +faststart \ "$OUTPUT_FILE" echo "导出完成:$OUTPUT_FILE"

-movflags +faststart是给网络播放优化的,可以把 moov 元数据移到文件头部,上传到视频平台后播放体验更好。

把三个步骤封装起来之后,Skill 3 的 SKILL.md 也很简单:

# 成片合成 将高光片段列表和原始视频合成为一个完整的成片文件。 使用场景: - 完成高光片段挑选之后 - 需要统一输出格式、分辨率和编码 - 需要自动添加片头片尾 流程: 1. 读取 highlights.json 2. 从原始视频裁剪高光片段 3. 生成 concat_list.txt 并拼接 4. 统一导出为 1080p MP4

7. 把 3 个 Skill 串起来:一条完整的自动剪辑流水线

三个 Skill 单独都能跑通,但它们要变成流水线,还需要一个编排层。这一步我不建议写复杂的调度框架,用一个简单的 shell 脚本或者 Makefile 就足够了。

以 Makefile 为例:

# 文件路径:Makefile INPUT_VIDEO := input.mp4 SEGMENTS_JSON := skills/rough-cut/segments.json SRT_DIR := srt_files HIGHLIGHTS_JSON := skills/subtitle-highlight/highlights.json OUTPUT_VIDEO := final_output.mp4 .PHONY: all rough-cut subtitle-highlight final-mix clean all: final-mix rough-cut: cd skills/rough-cut && python3 scripts/split_scenes.py $(INPUT_VIDEO) subtitle-highlight: rough-cut mkdir -p $(SRT_DIR) cd skills/subtitle-highlight && python3 scripts/extract_highlights.py \ ../rough-cut/segments.json ../../$(SRT_DIR) highlights.json 10 final-mix: subtitle-highlight bash skills/final-mix/scripts/build_final.sh $(INPUT_VIDEO) $(HIGHLIGHTS_JSON) $(OUTPUT_VIDEO) clean: rm -rf $(SRT_DIR) final_no_audio.mp4 $(OUTPUT_VIDEO)

build_final.sh 的作用是读取 highlights.json 里的片段信息,执行 ffmpeg 裁剪和拼接,最后调用 export_final.sh 导出。这里就不贴完整脚本了,逻辑和前面讲的裁剪、拼接保持一致。

有了这个编排层,你只需要在项目根目录执行:

make clean && make

就能从原始视频一路产出最终成片。中间任何一步失败,Makefile 会停在出错的地方,方便你单独调试。

从实际使用体感看,这套流水线最值钱的部分不是“全自动”,而是“可干预”。如果哪一期视频的高光选得不准,你只需要改 keywords 配置,然后重跑 subtitle-highlight 和 final-mix,不需要重新做粗剪。这种按 Skill 分步重跑的能力,是单个大脚本很难提供的。

8. 常见问题与排查思路

自动剪辑流程里,问题几乎都出在视频处理和脚本配置上。我把高频问题整理成了排查表:

问题现象可能原因排查方式解决方案
ffmpeg 无法识别输入文件文件路径含有空格或特殊字符检查命令是否对路径加了引号统一用变量传参,并在命令中加引号
生成片段过碎场景检测阈值太低查看 scenes 列表中切点数量调高 scene 阈值,比如从 0.3 调到 0.4
转写字幕为空视频本身无音轨或音轨过小用 ffprobe 查看音轨信息;检查转写时是否指定了语言调整音频增益;确认 --language 参数
concat 拼接失败片段编码参数不一致查看 ffmpeg 报错信息去掉 -c copy 改为重新编码;或统一裁剪参数
高光片段选错关键词设置不符合节目主题查看高光片段的 text_preview编辑 KEYWORDS 和 EMOTION_WORDS 权重
导出视频播放黑屏scale/pad 参数处理不当用播放器打开看是否全程黑屏检查 filter 链,确认 pad 颜色和尺寸
Makefile 执行时找不到脚本工作目录不对检查 make 的输出路径统一用项目根目录执行,脚本内部使用相对路径时注意切换目录

其中最容易忽略的是“静音阈值”问题。不同视频的底噪差异很大,录屏视频底噪低,现场收音底噪高。如果静音检测设置成固定的 -30dB,可能在底噪较高的素材上完全检测不出静音,导致粗剪切点过少。建议在 SKILL.md 里把阈值参数暴露出来,遇到特殊素材时通过 AI 对话直接调整。

9. 最佳实践:从玩具到流水线的工程建议

跑通 3 个 Skill 只是第一步。如果你想把这套自动化剪辑流程用到真实的每周更新场景,需要额外注意几点:

第一,每个 Skill 的输出都要带索引和版本。我在 segments.json 和 highlights.json 里都保留了原始时间戳,这样即使后续环节调整了策略,也能追溯一个片段最初来自原视频的哪个位置。真实生产中,素材可追溯比结果好看更重要。

第二,把规则写在代码里,而不是写在提示词里。关键词、权重、阈值这类东西如果写在 SKILL.md 的提示词里,AI 每次运行都有可能理解偏差;写在配置区里,AI 只会读取和使用,不会随机发挥。Skill 里“代码负责逻辑、提示词负责定位”的分工,是保持稳定性的关键。

第三,控制重跑成本。高光提取依赖语音转写,这是整个流水线里最耗时的部分。建议把转写结果缓存下来,文件名用视频文件名的哈希值加时间戳。如果只是调整了关键词权重,不需要重新转写,直接从缓存里读取 SRT 文件即可。

第四,尊重素材的合法授权。自动化剪辑不是让你随意抓取别人的视频来二创发布。使用歌手、讲师、直播主理人的内容做剪辑分发时,务必确认你有相应的处理权和传播权。版权合规应该是自动化流水线里默认的一环,不需要等到被投诉才开始考虑。

第五,参数配置要做到环境无关。我在本地跑通后,把 ffmpeg 路径、转写模型路径、输出目录全部改成了环境变量或配置文件。这样可以方便地迁移到另一台机器,也方便后续接 CI 或定时任务。

第六,用“影子模式”先试运行。别上来就全自动直接发布。建议先跑通流水线,把成片截图和文字摘要发给团队或朋友人工过一遍。确认效果稳定后,再把流程推到生产环境。

从实际价值来看,这套 Skill 方案最打动我的不是它省了多少时间,而是它把剪视频这件事从“手动操作工具”变成了“调试一套代码”。每一次效果不满意,我都是在调参数、调关键词、调 pipeline,而不是重新拖一遍时间轴。这种工作方式的转变,才是 AI 自动化剪辑真正值得投入的地方。

下一步,你可以先照着文中第 3、4、5、6 章的最小实现跑通一条视频,把这三个 Skill 装进你的 AI 编程助手工作区里,然后根据自己的素材类型调整关键词和阈值。跑通之后,再考虑加入自动封面、多平台导出、素材归档等扩展 Skill。你会发现,真正决定自动化剪辑上限的,是你对剪辑流程本身的拆解能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询