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 台のカメラアングルを、1 つの MP4 にまとめてレンダリングします。編集の判断は音声のエネルギーのみで行います。毎秒、最も音量の大きいマイクを使うカメラが選ばれます。出力はハードカット(またはハードカットと隅に表示する PiP)です。
セットアップとコマンド
実装はオープンソースの 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 は、単一カメラのサウンドトラックを、話者に応じてゲート処理したミックスに置き換えます。各時点で話している人の近接マイクの音声を残し、ほかの音声を抑えます。常時 2 マイクを合算する方法より、音漏れや部屋の残響音が重ならず、はるかにクリアです。--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 倍遅くなります。) - 向き。 スマートフォンでの撮影や、カメラを縦向きに取り付けた撮影では、映像が回転して記録されます。各カメラから 1 フレームを抽出(
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 をカバーするため、1 台のみの映像になることがあります。これは避けられません。max(delta)秒間は 1 台のみの導入になると想定してください。
編集品質 — polysync edit だけでは不十分な場合
polysync edit は毎秒、最も音量の大きいマイクに切り替えます。近接していて音漏れするマイクでは、各カメラのマイクがもう一方の話者の声も大きく拾うため、相手が話しているときでも近接/ゲストのマイクが最も大きい状態が続きます。その結果、編集ではそのカメラが過剰に選ばれ、カットが実際の話者に合わなくなります。「正しい話者に切り替える」ことが重要な場合は、EDL を手作業で編集して次の 2 つの対策を適用してください。
- マイクごとのベースライン正規化による話者判定。 秒ごとに、各マイクのエネルギーからそのマイク自身の中央値を引き、そのベースラインに対して最も高いマイクを選びます。これにより、実際に話している人が判定されます。(polysync の生の
cam[k] - mean(others)ではマイクごとのベースラインの差が除去されないため、音量の大きいマイクが優先されます。) - リズムを生むカットアウェイ(剪辑感)。 音声による判定だけでは、同じ映像が長時間続きます。1 つのショットを約 8〜10 秒までに制限し、約 3 秒のカットアウェイを挿入して、聞き手(リアクションショット)とワイドカメラを交互に映します。ワイドカメラのマイクは音量が小さいため、音声エネルギーだけでは選ばれません。導入や全体を見せるために、意図的に挿入してください。
このスキルでできること/できないこと
| できること | できないこと |
|---|---|
| 音声エネルギーに基づくカメラ切り替え | 顔/フレーミング検出(face_recognition、MediaPipe は使用しません) |
| 単一音源の音声(1 台のカメラのマイク) | 複数マイクのミックス/話者ごとのゲーティング |
| ハードカット、オプションで PiP の小窓表示 | クロスフェード/不透明度のトランジション/スライドアニメーション |
ffmpeg の concat + overlay フィルターによるレンダリング | HyperFrames の合成/<hf-clip> |
| カバー範囲を考慮(サイドカーファイルの範囲外にあるカメラは選択しません) | フレーム単位で正確なビート同期/VAD エッジでのカット |
顔追跡、フェードトランジション、字幕、または HyperFrames による合成が必要な場合は、このスキルの MP4 出力を使って hyperframes スキルを実行してください。
必須入力
元のカメラファイル(未加工)と、その隣にある .sync.json サイドカーファイル。 ソースがまだ同期されていない場合は、まず wjs-syncing-multicam を実行してサイドカーファイルを書き出してください。サイドカーファイルがない場合、カメラは delta=0、カバー範囲は全体とみなされます。
polysync edit は各サイドカーファイルから delta_seconds と overlap_in_reference を読み取り、カメラの音声エンベロープを基準タイムライン上に配置し、カバー範囲内でのみカメラをスケジュールします。polysync render-cuts / polysync render-pip は、EDL の deltas[] 配列を使って入力ごとに ffmpeg -itsoffset を適用します。
使用しない場合
- ソースが 1 つの場合 — 切り替え先がないため、video-segmentation を使用してください。
- すでに完成度の高い NLE タイムラインがある場合 — エディターと競合させないでください。
- フェードトランジション/オーバーレイ字幕/ブランドタイトルカードが必要な場合 — まずこのスキルを実行して短縮版 MP4 を作成し、それを wjs-overlaying-video または hyperframes に渡してください。
パイプライン
- 各入力のサイドカーファイルを読み取る →
delta_seconds[k]+overlap_in_reference[k]の一覧を取得します。 - 元のファイルからカメラごとのモノラル PCM @ 16 kHz を抽出します。
- 1 Hz のフレームレート(1 秒ごと)でログ RMS エンベロープを計算します。
- 各エンベロープを基準タイムライン上に配置し、
t_ref - delta_kでインデックスを参照します。カバーされていない秒は-infにして、選択されないようにします。 - 音声ソース = エンベロープの広がり(カバーされている秒の 90 パーセンタイル − 10 パーセンタイル)が最大のカメラ。カバー率に小さなボーナスを加えます。
- 1 秒ごとのスコア:
cam[k] - mean(other covered cams)。スコアが最も高いカメラを、話者が発話中である可能性が最も高いカメラとします。 - エディターが EDL を決定 — 2 つのモードがあります。
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 | ハードカットのみ。セグメントごとに trim+scale+pad を適用し、concat フィルターグラフで結合します。音声には audio_source カメラを使い、最初の EDL 行の開始位置に合わせてトリミングします。 |
polysync render-pip | ハードカット + 画面隅へのピクチャーインピクチャーオーバーレイ。メインカメラには EDL 行の cam を使います。PiP カメラはラウンドロビン方式で選択します(または行ごとの pip フィールドで指定します)。PiP は --pip-width(デフォルト 480 px)に合わせて拡大縮小し、設定可能な隅に配置します。オプションで白い枠線を付けられます。フェード/不透明度の調整はありません — 不透明なブロックとして表示/非表示になります。 |
どちらも入力ごとに -itsoffset deltas[k] を適用します。
実行前に相談すること
ユーザーに確認する、重要な設定は 3 つです。
- テンポ —
--mode rotation(滞在時間に変化があり、耳に優しい)か--mode greedy(音声エネルギーに追従し、切り替えが速い)を選びます。 - PiP — 使用するかどうか。使用する場合は、どの隅に配置し、幅をいくつにするか。
- 最小カット長 —
--min-dwellの下限。rotationのデフォルトは控えめな 8 秒ですが、トークヘッド映像では 4 秒にできます。
audio_source は自動選択されます。自動選択された音声が 30 秒ほど聞いて適切でない場合は、--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秒のクリップを試聴してください。広がりが大きいトラックでも、クリッピングや歪みが発生していることがあります。 - 調整する前に、75分全体に対して
polysync editを実行すること。 まずは2分のスライスで実行し(各カメラの抽出にはffmpeg -ss A -t 120を使用)、試聴して、--min-dwell/--modeを調整してから、全体に対して実行してください。 - 顔に基づいてフレーミングされると期待すること。 このスキルは映像を認識せず、音声のみを認識します。あるカメラのフレーミングが適切でも音量が小さければ、エディターはそのカメラを優先しません。手動で対処するには、
--audio-sourceとセグメントごとのpipオーバーライドを使用してください。 - 同期が間違っていたときに再レンダリングすること。 EDL には編集時点の
deltas[]が反映されています。後からサイドカーを修正した場合は、再レンダリングの前にpolysync editを再実行して EDL を再生成してください。 - 長い4Kオリジナルから動画の途中の区間を直接レンダリングすること=非常に遅くなります。
polysync render-cutsはフィルターグラフ内で(trim=start=…を使って)トリミングし、入力時に-ssでシークしません。そのため、EDL の開始位置がソースのかなり後方にあるクリップ(例:34分のファイルの開始から28分後にある90秒のセグメント)では、ffmpeg がその区間に到達するために t=0 から4K映像をデコードし、92秒のクリップに約20分かかります。対処法:まず各カメラの区間を、正確な高速シークを使って事前にカットします(ffmpeg -ss <start-2> -i src -ss 2 -t <dur> …— 2秒前まで高速シークし、その後2秒間を正確にデコード)。回転・カラーグレーディング・ターゲットフレームへのスケーリングを済ませたうえで、短く準備した区間にマルチカメラ EDL を連結します(時間は0起点なので低コストです)。すべてのカメラを同じ基準区間(source-local start = ref_start - delta_k)に合わせてカットし、同期を保ちます。これは/wjs-segmenting-videoでマルチカメラのセグメントをレンダリングする方法です。途中からの絶対時刻を指定した EDL を、先頭からデコードする処理に渡さないでください。