关于 wjs-editing-multicam
wjs-editing-multicam 是将同步的多机位素材制作成 MP4 的技能。它通过 polysync 命令行工具依据音频能量选择机位,输出硬切版本,也可添加画中画窗口。
主要功能
- 01从同步机位生成剪辑决策表
- 02依据音频能量选择机位
- 03渲染硬切剪辑
- 04添加角落画中画窗口
- 05按机位覆盖时间段进行选择
- 06应用机位旋转和 Log 转换
适用场景
- 01剪辑同步的多机位访谈素材
- 02制作带画中画的硬切版本
- 03将旋转拍摄素材处理为竖屏
- 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 分钟检查一下,否则整段内容都会渲染坏(我们就遇到过)。
- 色彩配置文件(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 倍。) - 方向。 手机拍摄或竖向安装的拍摄设备会录制旋转后的视频。每个机位提取一帧(
ffmpeg -ss 200 -i CAM -frames:v 1 f.jpg)并检查。部分相机(FX3)会写入旋转标记 → ffmpeg 会自动旋转,没问题。其他相机(物理上侧向转动的 FX6)不会写入任何标记 → 人物会横躺在画面中。按机位修正:--rotate 1:90(90 表示顺时针;如果画面上下颠倒,试试 270)。 - 交付视频方向。 小红书 / Reels / Shorts 使用竖屏格式——而这类素材通常也是竖屏拍摄的。使用
--width 1080 --height 1920 --fill渲染。默认设置(1920×1080,补边)仅适用于横屏;将竖屏素材混入横屏画面会产生黑色侧边栏(很难看)。 - 相机开始录制的时间不一致。 相机很少会在同一时刻开始录制;伴随文件中的
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。
流程
- 读取每个输入的 sidecar → 获取
delta_seconds[k]+overlap_in_reference[k]列表。 - 从原始文件中提取每台摄像机的单声道 PCM @ 16 kHz。
- 以 1 Hz 帧率(每秒)计算对数 RMS 包络。
- 将每个包络映射到参考时间轴,索引位置为
t_ref - delta_k;未覆盖的秒数设为-inf,因此永远不会被选中。 - 音频源 = 包络分布跨度(在覆盖秒数内计算第 90 百分位数 − 第 10 百分位数)最大的摄像机,并为覆盖比例提供少量加分。
- 每秒评分:
cam[k] - mean(other covered cams)。得分最高者 = 最佳当前说话人候选。 - 编辑器决定 EDL — 两种模式:
rotation(默认):在 [min_dwell=8、max_dwell=15] 秒范围内随机停留,并在每次切换时选择得分最高的已覆盖摄像机(≠ 当前摄像机)。greedy:滞后策略 — 保持当前摄像机,除非另一台摄像机在前瞻窗口内的得分超过它--switch-threshold。下限min_dwell=4,上限max_dwell=18。 两种模式都会在当前摄像机于镜头中途退出覆盖窗口时强制切换。如果t=0时没有摄像机覆盖(覆盖窗口从几秒后才开始),编辑器会从第一个有覆盖的秒数开始,并用摄像机 0 补齐前导部分。
- 输出 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。