mcpField
W
wjs-editing-multicam

wjs-editing-multicam

github.com/jianshuo创意与媒体137181 次安装今天更新
代码仓库

关于 wjs-editing-multicam

wjs-editing-multicam 是将同步的多机位素材制作成 MP4 的技能。它通过 polysync 命令行工具依据音频能量选择机位,输出硬切版本,也可添加画中画窗口。

主要功能

  1. 01从同步机位生成剪辑决策表
  2. 02依据音频能量选择机位
  3. 03渲染硬切剪辑
  4. 04添加角落画中画窗口
  5. 05按机位覆盖时间段进行选择
  6. 06应用机位旋转和 Log 转换

适用场景

  1. 01剪辑同步的多机位访谈素材
  2. 02制作带画中画的硬切版本
  3. 03将旋转拍摄素材处理为竖屏
  4. 04依据麦克风能量选择切换点

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jianshuo/claude-skills --skill wjs-editing-multicam

安装后在 Claude Code 中输入/wjs-editing-multicam确认已加载。

详细介绍

wjs-editing-multicam

将 N 个同步的机位合成为单个 MP4 文件。决策仅由音频能量驱动——每秒由麦克风声音最大声的机位胜出。输出为硬切(或硬切加角落画中画)。

设置与命令

此功能的实现位于开源 polysync pip 包中(https://pypi.org/project/polysync/ · https://github.com/jianshuo/polysync)——此技能不再附带自己的脚本。安装后,通过 CLI 使用:

python3 -m pip install -U polysync      # needs ffmpeg/ffprobe on PATH

polysync edit        CAM_A CAM_B CAM_C --out edl.json   # build the decision list
polysync render-cuts edl.json --out out.mp4             # hard cuts
polysync render-pip  edl.json --out out.mp4 --pip bottom-right   # cuts + corner inset

edit 和渲染器会自动读取每个输入文件的 .sync.json。如果同步文件尚不存在,请先使用 wjs-syncing-multicam(polysync sync)进行同步。

原始相机素材的渲染标志(何时使用各标志,请参见下文的 预检):

# Sony S-Log3 footage, shot vertical, FX6 cams turned on their side, for 小红书:
polysync render-cuts edl.json --out out.mp4 \
    --log slog3 \           # S-Log3/S-Gamut3.Cine -> Rec.709 grade
    --rotate 1:90 --rotate 2:90 \   # rotate cam1,cam2 90° CW (FX6 with no flag)
    --width 1080 --height 1920 --fill \   # vertical, crop-to-fill (no black bars)
    --duck-audio --audio-cams 0,1        # clean speaker-gated audio (cams 0,1 = the two lavs)

--duck-audio 会将单机位音轨替换为由说话者控制的混音:每个时刻保留当前说话者的近距离麦克风音频,并压低其余音轨(比持续混合两支麦克风的声音干净得多;后者会让串音和房间底噪叠加)。--audio-cams 0,1 会将控制范围限制为真正用于拾取说话者声音的麦克风——务必排除广角/房间机位,它的麦克风电平相近,但混响较重,否则也会被选中。(原因请参见下文的剪辑质量说明。)

预检——渲染前务必检查原始素材(经验之谈)

未经检查直接渲染相机原始素材,结果会出错。花 2 分钟检查一下,否则整段内容都会渲染坏(我们就遇到过)。

  1. 色彩配置文件(Log)。 Sony FX3/FX6 默认使用 S-Log3 / S-Gamut3.Cine——画面平淡、灰暗、对比度低。必须转换为 Rec.709,否则画面会显得褪色且不正常。检查 .XML 伴随文件中的 CaptureGammaEquation(s-log3-cine),或运行 ffprobe -show_entries stream=color_transfer。修正方法:--log slog3。(性能:LUT 会自动在缩小画面后应用——相同效果下,4K 的 3D LUT 比 1080p 慢约 4 倍。)
  2. 方向。 手机拍摄或竖向安装的拍摄设备会录制旋转后的视频。每个机位提取一帧(ffmpeg -ss 200 -i CAM -frames:v 1 f.jpg)并检查。部分相机(FX3)会写入旋转标记 → ffmpeg 会自动旋转,没问题。其他相机(物理上侧向转动的 FX6)不会写入任何标记 → 人物会横躺在画面中。按机位修正:--rotate 1:90(90 表示顺时针;如果画面上下颠倒,试试 270)。
  3. 交付视频方向。 小红书 / Reels / Shorts 使用竖屏格式——而这类素材通常也是竖屏拍摄的。使用 --width 1080 --height 1920 --fill 渲染。默认设置(1920×1080,补边)仅适用于横屏;将竖屏素材混入横屏画面会产生黑色侧边栏(很难看)。
  4. 相机开始录制的时间不一致。 相机很少会在同一时刻开始录制;伴随文件中的 delta/覆盖范围会显示这一点。开头的 N 秒可能只有一个机位(只有最先开始录制的机位覆盖 t=0)。这是无法避免的——预计会有 max(delta) 秒的单机位片头。

剪辑质量——何时 polysync edit 不够用

polysync edit 每秒会切换到麦克风声音最大声的机位。对于距离近且串音严重的麦克风(每个机位的麦克风也会大声拾取另一位说话者的声音),即使是另一位说话者在讲话,嘉宾的近距离麦克风仍可能声音最大,因此剪辑器会过多选择该机位,剪辑就无法跟随真正的说话者。在需要“切到正确说话者”时,可手动修改 EDL,采用以下两种修正方法:

  • 按麦克风分别进行基线归一化,以判断说话者。 每秒减去各麦克风自身的中位能量,然后选择相对于自身基线最高的麦克风 → 这才是实际在说话的人。(polysync 的原始算法 cam[k] - mean(others) 不会消除各麦克风的基线偏移,因此会偏向音量较大的麦克风。)
  • 插入过场镜头来调整节奏(剪辑感)。 仅靠音频判断会产生较长的静止镜头。限制单个镜头时长(约 8–10 秒),并插入约 3 秒的过场镜头,交替切到听众(反应镜头)和广角机位。广角机位的麦克风声音较小,剪辑器不会按能量选中它——因此应主动插入,用于建立场景/呈现整体画面。

这项技能是什么——以及不是什么

是不是
基于音频能量切换摄像机人脸/构图检测(不使用 face_recognition、MediaPipe)
单一音频源(一台摄像机的麦克风)多麦克风混音/按说话人门控
硬切,可选画中画插入画面交叉淡化/透明度转场/滑动动画
使用 ffmpeg concat + overlay 滤镜渲染HyperFrames 合成/<hf-clip>
考虑覆盖范围(不会选择超出其 sidecar 时间窗口的摄像机)精确到帧的节拍对齐/VAD 边缘切换

如果需要人脸跟踪、淡入淡出转场、字幕或 HyperFrames 合成,请在本技能输出的 MP4 基础上使用 hyperframes 技能。

必需输入

未经修改的原始摄像机文件及其放在文件旁边的 .sync.json sidecar。 如果源文件尚未同步,请先运行 wjs-syncing-multicam 生成 sidecar。缺少 sidecar 时,默认摄像机的 delta=0,覆盖范围为完整时长。

polysync edit 会读取每个 sidecar 中的 delta_seconds + overlap_in_reference,将摄像机的音频包络映射到参考时间轴上,并且只会在其覆盖时间窗口内安排摄像机。polysync render-cuts / polysync render-pip 会根据 EDL 的 deltas[] 数组,为每个输入应用 ffmpeg -itsoffset。

何时不使用

  • 只有一个源 — 没有可切换的对象;请使用 video-segmentation。
  • 已有精修好的 NLE 时间轴 — 不要与编辑器较劲。
  • 需要淡入淡出转场/叠加字幕/品牌标题卡 — 先运行本技能生成剪辑后的 MP4,再将其交给 wjs-overlaying-video 或 hyperframes。

流程

  1. 读取每个输入的 sidecar → 获取 delta_seconds[k] + overlap_in_reference[k] 列表。
  2. 从原始文件中提取每台摄像机的单声道 PCM @ 16 kHz。
  3. 以 1 Hz 帧率(每秒)计算对数 RMS 包络。
  4. 将每个包络映射到参考时间轴,索引位置为 t_ref - delta_k;未覆盖的秒数设为 -inf,因此永远不会被选中。
  5. 音频源 = 包络分布跨度(在覆盖秒数内计算第 90 百分位数 − 第 10 百分位数)最大的摄像机,并为覆盖比例提供少量加分。
  6. 每秒评分:cam[k] - mean(other covered cams)。得分最高者 = 最佳当前说话人候选。
  7. 编辑器决定 EDL — 两种模式:
    • rotation(默认):在 [min_dwell=8、max_dwell=15] 秒范围内随机停留,并在每次切换时选择得分最高的已覆盖摄像机(≠ 当前摄像机)。
    • greedy:滞后策略 — 保持当前摄像机,除非另一台摄像机在前瞻窗口内的得分超过它 --switch-threshold。下限 min_dwell=4,上限 max_dwell=18。 两种模式都会在当前摄像机于镜头中途退出覆盖窗口时强制切换。如果 t=0 时没有摄像机覆盖(覆盖窗口从几秒后才开始),编辑器会从第一个有覆盖的秒数开始,并用摄像机 0 补齐前导部分。
  8. 输出 EDL JSON。

EDL 架构(edl.json)

{
  "_about": "EDL produced by polysync.edit.autoedit. Times in reference timeline. Render commands apply ffmpeg -itsoffset deltas[k] per input.",
  "_help": {
    "inputs":        "Original media paths, in cam-index order (cam 0, cam 1, ...).",
    "deltas":        "Per-cam delta_seconds from each sidecar. Render uses ffmpeg -itsoffset deltas[k].",
    "duration_sec":  "Output duration in reference timeline.",
    "audio_source":  "Cam index whose audio track becomes the master. Single source — not a mix.",
    "coverage":      "[start, end] per cam in reference timeline.",
    "edl":           "List of {cam, start, end} segments. Times are reference-timeline seconds."
  },
  "inputs":       ["cam_a.MOV", "cam_b.MOV"],
  "deltas":       [0.0, 12.345],
  "duration_sec": 4512,
  "audio_source": 0,
  "coverage":     [[0.0, 4512.0], [12.345, 4499.835]],
  "edl":          [{"cam": 0, "start": 0, "end": 13}, {"cam": 1, "start": 13, "end": 28}, ...]
}

polysync edit 会直接将 _about + _help 写入文件,因此在任何编辑器中打开 JSON 都能了解其用途。

渲染

命令功能
polysync render-cuts仅硬切。通过 concat 滤镜图串接每段的 trim+scale+pad。音频 = audio_source 摄像机,并裁剪至第一行 EDL 的起始位置。
polysync render-pip硬切 + 角落画中画叠加。主画面摄像机 = EDL 行中的 cam;画中画摄像机按轮流顺序选择(或通过每行的 pip 字段指定)。画中画会缩放至 --pip-width(默认 480 px),放置在可配置的角落,并可添加白色边框。没有淡入淡出/没有透明度 — 以实色块开关。

两者都会为每个输入应用 -itsoffset deltas[k]。

运行前先讨论

需要与用户确认的三个实际选项:

  • 节奏 — --mode rotation(停留时长多变,听感更轻松)还是 --mode greedy(跟随能量,切换更利落)。
  • 画中画 — 要/不要。若要,放在哪个角落 + 宽度多大?
  • 最短剪辑时长 — --min-dwell 下限。rotation 默认 8 s,比较保守;访谈类视频可以设为 4。

audio_source 会自动选择;如果自动选择的效果听起来不对,可以试听 30 s 后通过 --audio-source <cam-index> 覆盖。

文件布局

working_dir/
  cam_a.MOV                 # ORIGINAL, untouched
  cam_a.MOV.sync.json       # from wjs-syncing-multicam
  cam_b.MOV                 # ORIGINAL, untouched
  cam_b.MOV.sync.json
  edl.json                  # from `polysync edit`
  multicam_render.mp4       # from `polysync render-cuts` OR `polysync render-pip`

常见问题

  • 不听音频就相信 audio_source。 分散度 + 覆盖率只是一个替代指标。提交前务必抽听一段 30 s 的片段——分散度高的音轨仍可能存在削波 / 失真。
  • 调整参数前就在完整的 75 min 视频上运行 polysync edit。 先截取 2 min 的片段(每个摄像机用 ffmpeg -ss A -t 120 提取),试听并调整 --min-dwell / --mode,然后再处理完整时长。
  • 期待由人脸驱动取景。 此技能看不到视频——只能处理音频。如果一个摄像机取景良好但声音较小,编辑器不会优先选择它。可使用 --audio-source + 按片段设置的 pip 覆盖作为手动解决方案。
  • 同步错误后重新渲染。 EDL 会在编辑时写入 deltas[]。如果之后修正了 sidecar 文件,请重新运行 polysync edit 以重新生成 EDL,然后再渲染。
  • 直接从较长的 4K 原始视频渲染中间的视频片段 = 极其缓慢。 polysync render-cuts 会在滤镜图中进行修剪(trim=start=…),不使用输入 -ss 定位,因此,如果片段的 EDL 起点位于源视频较深处(例如,一段 90 s 的片段位于 34 min 文件的第 28 min 处),ffmpeg 会从 t=0 开始解码 4K 视频,直到抵达该片段——渲染一段 92 s 的片段约需 20 min。解决方法:先用精确快速定位为每个摄像机预先剪出所需片段(ffmpeg -ss <start-2> -i src -ss 2 -t <dur> …——先快速定位到片段前 2 s,再精确解码 2 s),并提前完成旋转、调色和缩放以匹配目标画面;然后在这些短小的预处理片段上拼接多摄像机 EDL(从 0 开始计时,耗时很少)。所有摄像机都应剪出同一个参考片段(source-local start = ref_start - delta_k),以保持同步。这就是 /wjs-segmenting-video 渲染多摄像机片段时应采用的方法——绝不要向从头解码的流程传入中间时段的绝对时间 EDL。

评论

支持 Markdown