SuperAPI AI 工具集

edl-edit

设计与创作

查看项目

更新于 10-15 10:11

技能介绍

用途

edl-edit 用于把多片段视频剪辑表达为一份可审计的 JSON「编辑决策列表」(EDL)。它不鼓励为一次多切剪辑手写一次性的 filter_complex 然后丢弃,而是把剪辑写成 edit.json——一组片段,每个片段含 src、start、end 以及文字说明的 rationale——再用一条命令执行它:

uv run video-agent edl edit.json -o out.mp4

这样做的意义:剪辑成为可阅读、可 diff、可重复渲染的文本。一次修订就是「改两个数字再跑一遍」,而不是「重建 filtergraph」。rationale 字段迫使你写下每一处剪辑的原因(哪个 take 胜出、其他为何落选、切点为何在这里),既促成更好的决策,也为用户留下可检查的痕迹。

Schema

{
  "fps": 60, "width": 1920, "height": 1080,        // optional (these are the defaults)
  "grade": "luts/warm.png",                         // optional LUT for the whole cut (.cube or HALD .png)
  "audio_fix": "loudnorm=I=-14:TP=-1.5:LRA=11",     // optional filter chain on the speech bus
  "seam_fade": 0.015,                               // optional; click-killing fade at each cut
  "music": { "src": "inputs/bed.mp3", "gain_db": -18, "duck": true,
             "start": 0.0, "fade_in": 0.5, "fade_out": 2.0 },   // optional music bed
  "clips": [
    { "src": "takeA.mp4", "start": 1.89, "end": 60.81,
      "first_words": "Hey everyone",                 // doc only — the cut's first words
      "candidate_takes": ["A001","A004"],            // doc only — what you considered
      "rationale": "A004 cleanest complete take: zero ums, clean ending; A001 had a 5.8s dead pause" },
    { "src": "takeB.mp4", "start": 12.0, "end": 20.0,
      "audio_lead": 0.4,                             // J-cut: sound arrives 0.4s before picture
      "punch": [1.0, 1.06],                          // slow push over the clip (static shot)
      "rationale": "answer starts under the tail of the question so the cut disappears" },
    { "src": "talk.mp4", "start": 70.0, "end": 78.0,
      "vsrc": "roomcam.mp4", "vstart": 161.3, "vend": 169.3,
      "rationale": "audio stays on the mic'd talk; cut the PICTURE to the wide cam while the slide is static" }
  ]
}

start/end 是源时间线上的秒数(浮点)。剪辑是帧精确的(trim filter,而非 -ss 定位);渲染器把每个边界量化到帧网格上,因此 snap/tighten 写入的时间不会让画面与声音漂移。

first_words、candidate_takes、rationale 仅作文档——渲染器忽略它们,人读取它们。务必填写 rationale。

每个片段都会被归一化到 width×height(scale-to-fit + pad)并统一 fps,因此不同分辨率/fps 的片段可以干净地拼接(例如 4K take 挨着 720p)。

audio_lead 使该剪辑成为分离剪辑(+ = J-cut,− = L-cut)。这是防止剪辑显得跳切的主要手段——具体用多少见 cutting-rhythm 技能。视频与音频作为两条独立链拼接,因此 lead 永远不会失步。

punch 是缓慢的缩放推镜头(1.06 或 [1.0, 1.06])——为原本静态的镜头增添生气。

music 在同一次渲染中混入音乐床(循环覆盖、默认在语音下闪避),因此蒙太奇不需要二次重编码。audio_fix 在混音前作用于语音,所以闪避是在归一化后的对白上触发的。

seam_fade(默认 15 ms)作用于每个内部音频边界;作为淡变不可闻,但能消除对接拼接产生的咔哒声。设为 0 可禁用。

多机位切入(vsrc)

一个片段可以音频取自 src,而画面取自另一台摄像机,通过 vsrc/vstart/vend 指定。音频时间线保持连续(单一麦克风);只有视频切换——干净的机位切换,没有音频接缝。这就是表达「屏幕录制切入房间机位」的方式(寻找每个切入点的同步偏移见 editor 技能的多机位章节,通过音频互相关)。

从转录文本获取切点,而非拖时间线

从文本构建 EDL:transcribe src.mp4 --words(词级时间戳)得到说了什么,speech-segments src.mp4 得到帧精确的静音边缘。在转录中 grep 你要的那句,把其 start/end 写入 EDL。绝不用肉眼瞄时间线。

然后让 snap 精确放置切点,而不是手动微调数字:

uv run video-agent snap edit.json -o edit.snapped.json --to silence   # onto silence edges
uv run video-agent snap edit.json -o edit.snapped.json \
    --to beats --ref inputs/music.mp3 --tolerance 0.4                 # onto the music grid

它会打印每一处移动,并放过任何在 --tolerance 内没有候选的切点。

渲染前检查节奏

uv run video-agent edl edit.json -o /dev/null --report --dry-run

以条形图打印每个镜头的长度,并对单调的镜头长度、缺失的分离剪辑、过短的结尾镜头给出警告——这三件事会让一份正确的剪辑清单看起来很差。它不花费成本,能发现 JSON 中看不见的问题。根据 cutting-rhythm 技能采取行动。--draft 渲染快速的 480p 版本供自己验证。

通过重新转录输出进行验证

检查剪辑是否正确的最强手段,是转录你实际渲染出的内容并与意图比较:

uv run video-agent edl edit.json -o out.mp4
uv run video-agent transcribe out.mp4 --clean -o check.txt   # read it: right words, no fillers, nothing dropped

如果某个 take 本应无填充词,就在重新转录中 grep um/uh。如果某处剪辑落错,输出转录会显示出一个被截断或重复的词,这是帧检查发现不了的。在 EDL 中修正出问题片段的数字并重新运行。(仅内部验证——按 no-partial-previews 规则,向用户展示成品视频,而不是检查项。)

注意事项

grade / audio_fix 是原始 ffmpeg 应用于已拼接的剪辑——audio_fix 作用于拼接后的音频(适合放 loudnorm、acompressor;见 audio-edit),grade 是 LUT 路径,.cube 或来自 grade gen-lut 的 HALD .png(见 color-grade)。

一次重编码。整个 EDL 在单个 filter_complex concat 流程中渲染(h264_videotoolbox,aac 48k)——之后不要再做 stream-copy concat 后处理。现在这已包含音乐床和调色,因此没有理由加第二次处理。

此 LGPL ffmpeg 缺少 eq/drawtext——audio_fix 和 grade 必须使用可用的滤镜(loudnorm/acompressor/curves/colorbalance/lut3d/haldclut),而非 eq。

vsrc 切入必须与其覆盖的音频长度匹配。切入只替换画面;如果 vend-vstart ≠ end-start,画面会在剪辑剩余部分与声音脱节。渲染器会拒绝不匹配而非渲染它。

audio_lead 需要源素材能够向前延伸——J-cut 从片段入点之前借用音频,因此源中接近 0 处开始的片段无法获取较大的 lead。渲染器会报错而非静默缩短。它在片段 0 上被忽略(前面没有内容)。