粗剪
原始摄像机文件进,DaVinci Resolve 粗剪版本出。首次测试视频:原始 14:17,输出 10:16,而创作者的手动精剪为 10:32。
分工: Claude 负责粗剪,创作者负责精细修剪。不要试图交付精修版本,也不要过于保守,导致创作者必须重做明显的问题部分。
设置:填写这些
| 占位符 | 说明 | 示例 |
|---|---|---|
<FOOTAGE_DRIVE> | 原始素材所在位置,每个视频一个文件夹 | /Volumes/MyWorkDrive |
<LUT_PATH> | 可选的 LUT,相对于 Resolve 的 LUT 文件夹 | MyLuts/SLog3-to-709.cube |
WHISPER_MODEL (环境变量) | whisper.cpp 模型文件 | 默认 ~/.cache/whisper-models/ggml-small.en.bin |
RESOLVE_APP (环境变量,可选) | 非标准路径下的 Resolve 应用路径 | 默认 /Applications/DaVinci Resolve/DaVinci Resolve.app |
要求:ffmpeg、ffprobe、whisper-cli(whisper.cpp)、Python 3、以及暴露了 execute_resolve_code 的 DaVinci Resolve MCP 服务器。
运行
工作目录:使用会话临时工作区,例如 <scratchpad>/paperedit。技能目录如下:.claude/skills/paper-edit。
1. 查找素材
素材位于 <FOOTAGE_DRIVE>,每个视频一个文件夹,命名通常不严格。
find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<关键字>*" -not -path "*/.*"
如果匹配到多个文件夹,向用户确认。不要复制文件;Resolve 直接链接到它们。
2. 转录每个剪辑
bash <skill>/scripts/transcribe.sh "<FOOTAGE_DRIVE>/<文件夹>" "<work>"
生成 <clip>.json(词级时间戳)、<clip>.wav 和 clips.ndjson(含时长)。处理 15 分钟素材约需 90 秒。跳过已完成剪辑,因此可安全重新运行。
3. 亲自阅读转录文本
python3 <skill>/scripts/sentences.py "<work>"
全部阅读。 这是无法脚本化的部分。曾尝试过重复短语检测器但效果很差:它想剪掉 737 秒中的 428 秒,因为教师会刻意重复短语(“这个是有效的,这个是无效的”)。
4. 编写删除列表
<work>/cuts.json,每个删除操作一个对象,时间为从该剪辑起算的秒数:
[{"clip":"C0002","start":32.58,"end":39.76,"why":"口吃:'我意识到有时甚至……'"}]
删除这些内容:
- 旁白和对镜头说话:“那还不错,不骗你”、“这相机快没电了”、“这大概会是七分钟的视频”
- 错误开始,保留最后一次尝试。说话者经常重复一句话,第二次更好。
- CTA 的失败拿法。结尾处通常有 3-4 次;保留最后一个。
- 段落间的长时间静音、括号中的噪音(
[BLANK_AUDIO]、(键盘敲击声)、(翻动声)) - 半途而废并重新构建的句子:“我以前不做这个的原因是,我害怕,而且……”
- 句子内的简短重启,由逗号和重述从句标记:“我要求的回报只是一个简单的评论,而这正是,而添加评论部分……”从放弃的从句剪到重启处。这些只有 1-2 秒,阅读时容易忽略。
- Whisper 词级时间戳漂移约 0.5 秒。 在重述相同词语的错误开始时(“我喜欢进来提供,我喜欢开始”),剪辑应在第二个“我喜欢”的开始处结束,而不是第一次尝试的结尾,否则会残留一个词。
- 在保留词的
to偏移处开始剪辑,绝不能在其from处。 在一次测试中,剪辑在 40.30 开始,而保留词的范围是 40.19-40.92,导致最后一个词被切断,必须手动拖回。打印每个剪辑前的词偏移量,格式为from|to。 - 长时间的
[BLANK_AUDIO]之后,时间戳不可靠。 Whisper 在 30 秒静音后将第一个内容拿法的词挤在一起,导致剪辑在视频的第一秒就留下一个词片段。当拿法在死寂之后开始时,使用音频电平(ffmpegastats)查找语音实际开始位置,而不是相信词偏移量。
保留这些内容:
- 用于教学节奏的有意重复
- 仍然教授某些内容的题外话,除非用户另有说明
- 任何你不确定的内容。在摘要中标记,而不是剪掉。
5. 构建片段
python3 <skill>/scripts/segments.py "<work>"
生成 segments-v1.json(仅判断性剪辑)、segments-v2.json(同时将超过 0.50 秒的停顿修剪至 0.22 秒)和 cutlist.txt。可通过环境变量调整:MIN_GAP、KEEP_PAUSE、NOISE_DB。
它还会删除无语音的短片段:v2 中长度低于 1 秒且无语音电平的片段。这些是鼠标点击和瞥一眼笔记本电脑的碎片,在修剪后的停顿之间留下。可调整:BLIP_MAX、SPEECH_DB。
在展示给用户之前,阅读 cutlist.txt 中的每一行 join:。 它显示句子在每个剪辑处的读法。如果同一个短语出现在 | 的两侧,说明剪辑太短。
两个版本都很重要。 仅凭判断性剪辑,反馈是“整个视频,尤其是开头,有很大的停顿。”停顿修剪才是将 11:32 缩短到 10:16 的关键。不要将 KEEP_PAUSE 降低到大约 0.20 秒以下;否则听起来会很急促。
6. 在构建之前展示剪辑列表
粘贴摘要:原始长度、v1 长度、v2 长度、剪辑数量,以及显著的剪辑及其原因。用户否决他们不想要的。
7. 在 Resolve 中构建
需要 Preferences > System > General > External scripting using: Local(设置一次即可固定)。不要让用户打开 Resolve。首先运行以下命令;如果 Resolve 已关闭,它会启动并等待 API 响应:
bash <skill>/scripts/ensure_resolve.sh
如果 Resolve 正在运行但超时,说明脚本功能已关闭;这是唯一需要用户修复的问题。
写入 <work>/params.json:
{"project":"<视频名称> - YYYY-MM-DD","work":"<work>",
"files":["<FOOTAGE_DRIVE>/<文件夹>/C0001.MP4","..."],
"fps":23.976,"width":1920,"height":1080}
然后调用一次 execute_resolve_code:
PARAMS = "<work>/params.json"
exec(open("<skill>/scripts/resolve_build.py").read())
多个视频:逐个构建,绝不能并行调用工具。 Resolve 只有一个当前项目,因此两个构建会冲突。曾有一次两个构建同时运行,导致一个 v2 为空,尽管脚本报告了每个添加的条目。每次构建后,自行检查每个时间线的条目数量。
将项目命名为 <视频> - YYYY-MM-DD,这样同名的项目不会混淆。它会创建一个新项目,导入剪辑,并构建 Paper Edit v1 和 Paper Edit v2 (tight)。现有内容不会被触及。这是 execute_resolve_code 的许可用途;append_to_timeline 无法设置入/出点,因此没有替代工具。在会话中第一次使用时向用户展示代码。
如果无法访问 Resolve(云/计划任务运行,或 ensure_resolve.sh 失败):编写一个 FCPXML,包含一个 asset-clip 元素对应每个片段,包含以 frames*1001/24000s 为单位的 start 和 duration,让用户导入。结果相同,多一次点击。
8. 交接
告知用户两个时间线都已存在,建议先查看哪个(v2),以及 v1 是安全网,以防 v2 感觉剪辑过头。然后询问剪辑是否锁定,因为叠加层在后面(参见 video-overlays,如果你有的话)。
9. 推拉效果(可选的第三时间线)
静态构图变化能让 talking-head 视频更耐看。Resolve 的 API 没有关键帧访问,因此无法自动实现慢推效果;只能做静态的逐片段构图(“某些剪辑稍微放大一点”)。
将每个变化与转录文本关联,而不是使用时间计时器。 基于计时器的版本感觉随意。在重磅台词或新话题开始时进行推拉效果,使其有意义。
写入 <work>/framing.json:
[{"clip":"C0002","at":361.40,"framing":"med","why":"提示 3"},
{"clip":"C0002","at":371.80,"framing":"close","why":"'这部分是关键'"}]
at 是从 sentences.py 获取的句子开始时间。然后运行 python3 <skill>/scripts/punchins.py "<work>",并在 params.json 中设置 "punchins": true。它会在标记落在某个片段内时,在该句子开始附近最安静的点分割该片段,因为说话者经常长时间连续说话,没有停顿,否则变化会滑动延迟。
如果用户在 Resolve 中手动修剪了 v2,他们的时间线就是最终剪辑。 读取其条目(GetLeftOffset/GetDuration,帧数 x 1.001/24 = 秒)到 segments-locked.json,使用 SEGMENTS=segments-locked.json 运行,并仅向现有项目添加 v3,设置 "timelines": ["v3"]。目标是每约 20-40 秒进行一次变化:每个新话题时使用广角,教学时使用中景,重磅台词时使用近景。构建器会在每次变化处放置一个蓝色标记,标明原因,使逻辑可见。
构图参数:wide 1.00,med 1.11(倾斜 -12),close 1.21(倾斜 -24)。
如果用户在修剪 v2 的同时对其进行了调色,v3 是从头开始构建的,仅应用 LUT,因此在构建 v3 后立即将 v2 的调色复制到 v3 上:
src = v2.GetItemListInTrack("video", 1)[5] # 任意已调色的 v2 条目
src.CopyGrades(v3.GetItemListInTrack("video", 1)) # 跨时间线有效;缩放/倾斜保留
使用 GetNodeGraph().GetToolsInNode(1) 验证每个 v3 条目。不要使用画廊路径(GrabStill + ExportStills 到 .drx):通过 API 导出会返回 False。如果使用了 GrabStill,请删除该静帧,保持画廊整洁。
读取锁定的 v2:GetLeftOffset() 和 GetDuration() 提供源帧数。第一个片段告诉你起始部分是否被修剪。将锁定片段与 segments-v2.json 进行差异比较,并记录哪些发生了变化,以便校准下一次编辑。
10. 调色
在 params.json 中设置 "lut": "<LUT_PATH>",将其应用于节点 1 上的每个剪辑。如果相机拍摄的是 log 配置文件(例如 S-Log3),未经调色的素材看起来平淡灰暗,因此设置 LUT 是有价值的。API 无法添加第二个节点;对于多节点调色,手动调色一个片段,然后使用 CopyGrades 推广。
11. 讲解时叠加照片(可选)
当讲解者提到他们拥有的照片时,将照片放置在 v3 的 V2 轨道上,使用白色背景。
- 卡片,而非幻灯片。 在纯白色背景上渲染 1920x1080 PNG:三张肖像并排(缩放至 h840,间距 50px),两张肖像(h880,间距 60px),或一张风景照(h900)。根据讲解内容对照片进行分组。
- 将每张卡片与锁定转录文本中的句子开始时间对齐,并在下一句话时切换卡片。每张卡片约 2-5 秒。仅在被描述时才显示照片。
- 将其作为精确时长的 ProRes .mov 导入,而非静态图片。 静态图片进入 Resolve 时固定为 2 秒并相互重叠。编号名称(
card1.png、card2.png)作为单个图像序列导入,因此使用文字名称。使用ffmpeg -loop 1 -framerate 24000/1001 -i x.png -frames:v N -c:v prores_ks -profile:v 3渲染。 - 对于 .mov,
AppendToTimeline需要endFrame等于帧数(不是 count-1),否则每张卡片会少一帧,导致说话者在卡片之间闪回。传递"mediaType": 1以避免附带音频。 - 将轨道命名为 "<话题> 照片",将卡片放入其自己的媒体池文件夹,并且绝不对它们应用 LUT(它们已经调色)。
- 在放置之前,在聊天中向用户展示卡片的联系表。
值得记住的事实
- 来自实际编辑的校准: 在 v2 之后,创作者通常从一个约 10 分钟的剪辑中手动移除 10-20 秒。大部分是片段边缘的帧级收紧,以及重述的句子,其中某个观点被说出然后在几秒钟内以更好的方式再次说出。当一个句子重述了前一个句子时,剪掉第一个版本。这与有意的教学重复不同,后者重复短语跨越不同部分,而不是连续重复。当同一个观点在相距较远的地方被提出两次时,将较弱的拿法标记为可能的剪辑点。
- 通常的担忧是剪辑过多,导致需要重新添加内容,因此只凭证据收紧,绝不凭直觉。
- 示例源格式:4K 23.976 MP4,48kHz 音频;交付时间线 1920x1080 23.976,从 01:00:00:00 开始。根据需要调整
params.json中的fps/width/height。 - 23.976 的时间码每秒计 24 帧:
frames = round(seconds / 1.001 * 24)。 AppendToTimeline将endFrame视为排他性:传递你想要的最后一帧之后的帧。如果使用“包含,减 1”规则,则每个片段都会丢一帧(在 10 分钟的时间线上约 4 秒),并且任何单帧片段都会消失。- 一些说话者几乎不使用填充词;在围绕填充词移除构建之前进行检查。
- 大约 20% 的原始 talking-head 素材是可移除的,其中约四分之三是判断性内容(拿法和重启),四分之一是死寂。
- Whisper 模型:
ggml-small.en.bin足够准确;它会误听少数单词,这对于剪辑点不重要,但如果引述说话者则很重要。
相关技能
video-overlays:动画图形,在剪辑锁定后运行(如果已安装)video-reels:来自同一素材的竖版剪辑(如果已安装)video-thumbnails:缩略图和标题(如果已安装)lapel-sync:当音频是通过单独的领夹式麦克风/录音机录制时,首先运行