Communitygithub.com

视频剪辑

将一段未经剪辑的长视频快速转化为紧凑、可观看的初剪版本,由人类做出编辑决策,脚本负责精确执行。

视频剪辑 是什么?

这是一项为AI代理(如Claude Code、Cursor、Codex等)设计的专业技能,用于将原始、未编辑的长视频(YouTube URL或本地文件)转化为紧凑、可观看的“初剪”。该技能的核心原则是:人类(你,模型)负责做出“保留什么”的编辑决策,而脚本则负责机械性的精确操作,如边界对齐、静音回收、内存安全渲染和自我验证。支持的平台包括任何具有正确依赖项(yt-dlp、ffmpeg、Python + faster-whisper)的环境。工作流程从视频下载开始,经过音频转录、分析诊断、人工编辑决策、自动边界扩展和变速渲染,最后进行严格的自检,包括重新转录、黑帧检测、音画同步检查和静音检测。该技能特别强调decisiveness(果断决策)、self-check(自检不可妥协)和memory-safe render(内存安全渲染),并提供了与`/video-understand`技能共享证据层的集成能力。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/WhiteTowerAI/cut-as-code/tree/main/skills/video-cut

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

视频剪辑 是做什么的?

将一段未经剪辑的长视频转化为紧凑、可观看的初剪——果断、内容感知且自我验证。人类(你,模型)负责做出“保留什么”的编辑决策;附带的脚本负责机械性的精确操作(边界对齐、静音回收、内存安全渲染、自检)。

使用时机

  • 需要将原始/未剪辑的视频(YouTube URL 或本地文件)变得更紧凑。
  • 要求是“将其减半”、“剪掉无聊的部分”、“制作一个初剪/粗剪”。
  • 不适用于:逐字的填充词微调整、多机位B-roll组装、颜色/音频润色——这些属于后续的P1/P2精修环节。此技能是P0:验证分析结果 + 产生一个可靠的剪辑。

依赖项

/video-understand 是先决条件。请先运行它,并使用其验证后的媒体、转录文本、分析结果和时间线,而不是在此技能中重新创建。在开始之前,请验证它是否已安装。如果未安装,请警告用户缺少此先决条件,并在处理媒体前停止。

激活任何包含以下依赖项的环境(不要假定特定的 conda 环境名称):

  • yt-dlp(下载),ffmpeg/ffprobe(剪辑/渲染/探测)位于 PATH 上
  • 带有 faster-whisper 的 Python(CPU 可用:device=cpu, compute_type=int8) 首先检查:yt-dlp --version,ffmpeg -version,python -c "import faster_whisper"。

项目协议工作流程

使用以下持久化项目文件:

work/cut/edit-plan.json          # 仅手工编写的保留/丢弃决策
work/timeline.json               # 生成的精确范围 + 素材/节目映射
review/01-cut/cut-summary.md
review/01-cut/timeline-map.png
review/01-cut/boundary-review.mp4
review/01-cut/full-proxy.mp4  # 可选的整节目节奏审查

每个规范决策具有稳定的 id、action(keep 或 drop)、start_s、end_s、reason 以及语义/转录 evidence_refs。保持决策按时间顺序;V1 不支持重新排序或重复的源素材片段。

重用共享的证据层,而不是重新转录或诊断:

python skills/video-understand/scripts/transcribe.py work/cache/audio16k.wav work/understand/transcript
python skills/video-understand/scripts/analyze.py work/understand/transcript.json work/understand/analysis.json

现有的精确脚本接受规范计划。扩展单词安全的边界,可选地分配线性变速,然后生成共享时间线:

python skills/video-cut/scripts/build_edit.py work/cut/edit-plan.json work/understand/transcript.json work/cache/edit-final.json
python skills/video-cut/scripts/assign_speed.py work/cache/edit-final.json work/understand/transcript.json
python skills/video-understand/scripts/build_timeline.py work/cache/edit-final.json work/timeline.json --fps-num SOURCE_FPS_NUM --fps-den SOURCE_FPS_DEN

使用来自 work/understand/media.json 的确切有理数 FPS;从不将 30000/1001 舍入为 30/1。审查 timeline-map.png 和简短的 boundary-review.mp4。仅在必须审查整节目节奏时生成 full-proxy.mp4。将结果写入 cut-summary.md,并将操作检查报告指向该文件。

记录时间线贡献及其所需的源输入,更新操作整数 revision,并将 based_on 设置为所消耗的确切理解修订版本:

"render": {
  "kind": "timeline-transform",
  "input": "../input/original-video.mp4",
  "plan": "timeline.json"
}

在所有修订检查通过后,共享交付渲染器对活动序列进行编码。

独立兼容性工作流程

以下旧版文件和命令在迁移期间仍然受支持。build_edit.py 同时接受 edit_coarse.json 和规范的 decisions[];cut_render.py 同时接受 edit_final.json 和 timeline.json;此技能的 transcribe.py 是围绕 ../video-understand/scripts/transcribe.py 的兼容性包装。

将所有中间文件保存在 work/ 下,交付到项目根目录:

work/source.mp4            # 下载的原始文件
work/audio16k.wav          # 用于 whisper 的 16k 单声道音频
work/transcript.json/.srt  # 单词级别的时间戳
work/analysis.json         # 诊断(静音、填充词、连续讲话)
work/edit_coarse.json      # *** 你的编辑决策(手写) ***
work/edit_final.json       # 扩展的紧凑渲染片段(生成;包含每个片段的速度)
work/selfcheck/            # 剪辑重新转录 + 帧连接检查
first_cut.mp4              # 可交付产物
first_cut_report.md        # 编辑 + 自检报告

工作流程(6 步)

1. 下载

最高可访问质量 + 音频。默认播放器客户端经常失败(不可用/DRM/登录要求)。可靠的备选方案是 android 客户端:

yt-dlp --extractor-args "youtube:player_client=android" \
       -o work/source.mp4 "<URL>"

如果无需登录只能获取混合的 360p(格式 18),请接受它并记录此限制——HD DASH 经常受到 DRM/登录保护。然后提取音频:

ffmpeg -y -i work/source.mp4 -ac 1 -ar 16000 work/audio16k.wav

2. 转录(单词级别)

python scripts/transcribe.py work/audio16k.wav work/transcript [base.en]

生成 work/transcript.json(片段 + 每个单词的开始/结束时间)和 .srt。 使用 faster-whisper, CPU/int8, VAD 开启, word_timestamps=True。 非英语: 传递一个多语言模型 + --lang,例如 python scripts/transcribe.py work/audio16k.wav work/transcript medium --lang zh (.en 模型仅支持英语)。先在一个短样本上验证语言。 注意: Whisper 会去除大多数发声的“嗯/呃”——它们无法通过转录测量,因此填充词检测必须将下面的词汇搜索与静音间隙分析相结合,而不是仅依赖转录文本。

3. 诊断(“看” + “读”)

python scripts/analyze.py work/transcript.json work/analysis.json

揭示:开头的静音、结尾的静音、单词间静音 ≥0.8 秒(以及它们跟随的单词)、填充词计数、wpm、讲话比例、近似重复、长度 >40 秒的独白片段(可能的闲聊候选)。

要看画面,每约 2 秒采样一帧形成联系表,并亲自阅读;确认场景结构/查找黑色或损坏帧:

ffmpeg -y -i work/source.mp4 -vf "fps=1/2,scale=240:-1,tile=10x10" -frames:v 1 work/contact.png
ffmpeg -i work/source.mp4 -vf "blackdetect=d=0.1:pic_th=0.98" -an -f null -

对于单个静态的说话头像镜头,没有场景切换——预期如此,并注意后续的跳跃剪辑是正常的,而不是故障。

4. 决定剪辑——手写 edit_coarse.json

这是编辑核心。阅读转录文本 + 分析结果,然后编写一个保留块和丢弃跨度的粗略计划,这些块和跨度无间隙/无重叠地平铺整个时间线,每个块/跨度都有 in、out 和一行 reason。将缓慢的前言压缩为少数高价值的精华部分;保留主旨内容为较大的块;丢弃明显的离题/闲聊。保持时间顺序;规范的 V1 时间线拒绝重新排序。目标是大约将运行时间减半。

  • 格式规范 + 一个真实的工作示例:reference/edit_coarse.schema.md。
  • 将每个块的边界对齐到句子/小句的结束——绝不在句子中间或口吃处开始/停止。使用:
    python scripts/inspect_bounds.py work/edit_coarse.json work/transcript.json
    
    它接受传统 keep[] 和规范 decisions[] 计划,并打印跨越每个边界的单词,以便你可以将它们调整到干净的边界上。

5. 扩展 → 自动变速 → 渲染

将粗略块转换为紧凑、无静音的渲染片段,标准化讲话速度,然后渲染:

python scripts/build_edit.py   work/edit_coarse.json work/transcript.json work/edit_final.json 1.5
python scripts/assign_speed.py work/edit_final.json   work/transcript.json   # 添加每个片段的速度
python scripts/cut_render.py    work/edit_final.json   work/source.mp4 first_cut.mp4
  • build_edit.py 在大于 SPLIT_GAP(第 4 个参数,例如 1.5 秒)的内部暂停处拆分每个块,并将每个边界修剪到静音内部(前导 0.10 秒 / 尾部 0.30 秒),这样就不会剪掉任何单词,同时回收静音时间。较低的 SPLIT_GAP = 更紧凑但更跳跃;对于语速慢、深思熟虑的说话者,建议使用 1.5 而不是 0.6(避免过于琐碎的微小剪辑)。
  • assign_speed.py(自动变速)——按 decision_ref 分组渲染片段,测量每个手写保留决策的讲话速度,并将一个共享的 speed 因子以及每个片段产生的 out_dur 写回 edit_final.json。速度已在舒适范围内的保持在 1.0;超出范围的速度仅移动到最近的死区边界。相邻决策块之间的差异不超过 0.08 倍,以避免“抽动”式的连接。它仅改变速度——从不改变保留的内容。在渲染前阅读打印的表格:
    • 指标:单词/分钟(英语)——对于 CJK(中文/日语/韩语)自动切换为字符/分钟。
    • 默认值是首次运行的起点,而非验证过的常数:死区 145–185 WPM,速度限制在 1.0–1.3。这是仅加速:说话慢的决策块可以被加速,而自然快的说话保持 1.0。短的决策块(<3.5 秒 / <6 个单词)噪音太大无法测量,将继承全局因子。
    • 速度是在静音回收后测量的,因此比总 WPM 更高,更接近发音速率。打印表格的审查是关键:在渲染前目测并调整 deadband 以匹配说话者,不要盲目相信默认值。
    • 旋钮(k=v):mode=segment|global|off(默认 segment;global=整个视频一个因子,off=禁用),deadband=lo,hi,min_speed=/max_speed=,min_seg=/min_words=,lang=auto|en|cjk。要完全跳过此功能,只需不运行此步骤——cut_render.py 将缺失的 speed 视为 1.0。
  • cut_render.py 使用 N 个独立的 seeked 输入 + concat 过滤器,单次重新编码。这是强制的:从一个解码输入上 N 次修剪会使 ffmpeg 缓冲整个解码流(对于长视频可达数十 GB)。参见 reference/pitfalls.md。 当片段带有 speed 时,它重新计时每个输入(视频的 setpts / 音频的 atempo),并在 concat 之前标准化每个输入的 fps/时间基准/采样率,以便音视频保持锁定;如果没有速度,它回退到原始的确切图形。
  • 最终比较: video-edit-compare 读取规范时间线加上实际的最终交付产物。它将最终像素投影回源时间,将变速剪辑拉伸到它们的源持续时间,并将丢弃的范围显示为黑色。

6. 自检——在通过此检查之前不要声明完成

# 协议精度回归检查(从仓库根目录运行)
python skills/video-cut/scripts/check_project_protocol.py
# 重新转录完成的剪辑
ffmpeg -y -i first_cut.mp4 -ac 1 -ar 16000 work/selfcheck/cut_audio16k.wav
python scripts/transcribe.py work/selfcheck/cut_audio16k.wav work/selfcheck/cut_transcript
# 内容 + 填充词 + 边界检查
python scripts/verify_cut.py work/edit_final.json work/transcript.json work/selfcheck/cut_transcript.json
# 帧 / 黑色 / 连接检查(连接时间使用变速后的 out_dur,因此保持准确)
python scripts/selfcheck_frames.py work/edit_final.json first_cut.mp4 work/selfcheck
# 音画同步 + 无残留静音
ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffprobe -v error -select_streams a:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffmpeg -i first_cut.mp4 -af silencedetect=noise=-32dB:d=1.5 -f null -

通过阈值:

检查项通过条件
黑帧无
连接帧干净——仅自然头部跳跃,无黑色/冻结/撕裂
音画同步视频与音频时长差约 1 帧(≈30ms);总时长 ≈ 变速后的 final_duration_s_after_speed
静音 ≥1.5秒0(讲话比例应显著上升)
丢弃/重复的片段无——所有关键内容都存在(difflib ~0.90 可接受;较低比例通常是针对含糊不清讲话的二次转录噪音,而非内容丢失——在归咎于剪辑之前,通过关键词存在来验证)
被切断的半句无——边界落在静音/句子结束处

关于填充词的诚实说明: 段落级别的剪辑不会实现“几乎没有填充词”。每分钟的密度甚至可能上升,因为保留的内容是对话性质的。如实报告这一点;单词级别的填充词去除属于 P1/P2(并且会使单次拍摄的讲话头像看起来明显跳跃)。

最后

编写 first_cut_report.md:源摘要、剪切了什么及原因、自检表以及任何诚实的注意事项(来自 360p 源的质量上限、填充词密度等)。如果应用了变速,请透露:重新计时的片段数量及速度范围(来自 assign_speed.py 的表格 / speed_params),以便读者知道剪辑不是 1:1 实时。还要注意,verify_cut.py 的每分钟填充词数字在加速后看起来略高(相同单词,更短的分钟)——这是一个报告伪像,而不是添加了填充词。

关键原则(来之不易的)

  • 你决定内容;脚本决定帧。 手写 edit_coarse.json;让 build_edit.py 做精确,assign_speed.py 做速度。
  • 速度影响节奏,不影响内容。 自动变速为来自一个 decision_ref 的所有渲染片段提供相同的速度,仅将超出范围的节奏移动到最近的死区边界,将相邻决策的差异限制在 0.08 倍以内,并将输出限制在 1.0–1.3。atempo 保留音调。审查表格;设置为 mode=off 或跳过此步骤以禁用。
  • 绝不剪掉一个单词。 边界始终落在静音内部。
  • 仅内存安全渲染(N 个 seeked 输入 + concat)。绝不对一个输入进行多次修剪。
  • 果断决策。 做出合理判断并继续前进;不要过度询问。
  • 自检不可妥协。 在声称完成之前重新转录 + 帧检查。
  • 参见 reference/pitfalls.md 获取陷阱和修复方法的完整列表。

Individual skills in this repo

This repo contains 8 individual skills — each has its own dedicated page.

相关技能