Communitygithub.com

ラペルシンク

カメラ映像と、別録りしたラペルマイクやフィールドレコーダーの音声トラック(例:Tascam DR-10L)を同期し、DaVinci Resolveのプロジェクトに組み立てます。レコーダーの分割ファイルを連結し、単語と波形のマッチングで各クリップの正確な位置を特定し、クリップごとにラペル音声をスライス。クリッピングをチェックし、同期済みのタイムラインを新しいResolveプロジェクトに構築します。「ラペルを同期」「音声を同期」「レコーダーを合わせる」「ラベリアを使った」など、独立した音声フォルダがある撮影(トーク、イベント、ワークショップ)でトリガーしてください。ペーパー編集やビデオリールの前に実行します。

ラペルシンク とは?

このスキルは、カメラで撮影した映像と、別録りしたラペルマイクやフィールドレコーダー(例:Tascam DR-10L)の音声トラックを正確に同期するためのものです。ライブイベントなど、カメラ内蔵マイクの音質が不十分な場合に、高品質なラペル音声を各映像クリップに割り当てます。レコーダーの分割ファイルを連結し、Whisperを使用してカメラ音声とラペル音声の両方を文字起こし。4単語のユニークなランと波形の相互相関を組み合わせて、各クリップのオフセットをミリ秒単位で特定します。その後、クリップごとにラペル音声をスライスし、24ビットのWAVファイルと、ペーパー編集やビデオリールなどの後続スキルが使用する16kHzモノラルファイルを作成。最終的に、同期済みのタイムラインをDaVinci Resolveプロジェクトとして構築します。このスキルは、ffmpeg、Whisper.cpp、Python、DaVinci Resolve(MCPサーバー経由)を必要とし、Claude Codeや類似のコード実行型AIエージェントと連携して動作します。トークイベントやワークショップなど、独立した音声トラックが別にある撮影に特に有用です。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/beachyphotoandfilm-arch/video-skills/tree/HEAD/skills/lapel-sync

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

ラペルシンク は何をしますか?

カメラのクリップと別録りのレコーダートラックを入力として、クリップごとに1つのラペル音声スライスと、同期済みのResolveタイムラインを出力します。初回テストはライブトークで実施:59分のレコーダートラックに対して5つのカメラクリップ。すべてのクリップが20ミリ秒以内に着地し、1フレームを大幅に下回りました。

なぜ重要か: ライブイベントではカメラのマイクは部屋の反対側にあります。その音声は使い物にならず、ラペルだけがクリーンな音声です。このスキル実行後、<work>/<clip>.wav と <clip>.json がラペル音声になるため、ペーパー編集やビデオリールは何も変更があったことを知らずにクリーンな音声と文字起こしを読み取れます。

セットアップ:以下を入力

プレースホルダー説明例
<FOOTAGE_DRIVE>生映像がある場所。ビデオごとに1フォルダ、レコーダーファイルは audio/ サブフォルダ内/Volumes/MyWorkDrive
<SYNC_OUT>フル品質のラペルスライスの出力先~/Movies/<video>-sync
<LUT_PATH>オプションのLUT、ResolveのLUTフォルダからの相対パスMyLuts/SLog3-to-709.cube
WHISPER_MODEL (環境変数)whisper.cppのモデルファイルデフォルト ~/.cache/whisper-models/ggml-small.en.bin

要件:ffmpeg、ffprobe、whisper-cli (whisper.cpp)、Python 3(numpy と scipy は自動で ~/.cache/lapel-sync-venv にインストール)、execute_resolve_code を公開するResolve MCPサーバーを伴うDaVinci Resolve、および paper-edit スキル(ensure_resolve.sh 用)。

実行方法

作業ディレクトリ:セッションのスクラッチパッド、例:<scratchpad>/<video>。スキルディレクトリは以下 .claude/skills/lapel-sync。フル品質のスライスは <SYNC_OUT> に出力。

zshの注意点: インラインシェルでは $ss:end_sample は :e を修飾子として解析し、テキストを食べてしまいます。常に ${ss} と記述してください。

1. 映像と音声を見つける

<FOOTAGE_DRIVE> 上にビデオごとに1フォルダ。レコーダーファイルは audio/ サブフォルダにあります:

find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<keyword>*" -not -path "*/.*"
ls "<folder>" "<folder>/audio"

例えばTascam DR-10Lは、000_YYMMDD.wav、001_... のように15分ごとに分割し、さらに _D ツインファイルを書き出します。_D ファイルはデュアルレコードのセーフティトラックで、約20 dB低いです。メインファイルを使用し、_D はクリッピング部分の修正用に保持します。

2. レコーダーファイルを連結する

bash <skill>/scripts/stitch.sh "<folder>/audio" "<SYNC_OUT>/lav-master.wav"

各ファイルのBWF time_reference(真夜中からのサンプル数)を読み取り、すべてのファイルが直前のファイルの終了位置から正確に始まっていることを確認します。サンプル連続している場合はロスレスのストリームコピー。ギャップがある場合はその分の無音を挿入し、マスターが壁掛け時刻に一致するようにし、そのサイズを警告します。

3. 両方の音声を文字起こしする

bash <skill>/scripts/transcribe_sources.sh "<folder>" "<SYNC_OUT>/lav-master.wav" "<work>"

すべての出力は <work>/sync/ に格納され、<work> 自体には置かれないため、ペーパー編集の sentences.py が読み取ることはありません。カメラ音声は最初に強く増幅されます(highpass=f=120,volume=40dB,alimiter、16kモノラル)。これは多くの場合 -65 dB程度であるためです。既に完了した処理はスキップするため、自由に再実行できます。

ラペルは音声1時間あたり約8分かかります。バックグラウンドで実行してください。Whisperは単語のタイミングを <work>/sync/lav.log にストリーミングし、align.py は lav.json がまだ書き込まれていない場合にそのログを読み取るため、ラペルの文字起こしが完了する前にアライメントを開始できます。文字起こしが完了していないクリップは「N単語のみ一致」と報告するだけなので、完了後に再実行してください。

4. アライメント

python3 <skill>/scripts/align.py "<work>"

<work>/sync/sync.json を書き込みます。初回実行時は ~/.cache/lapel-sync-venv にnumpyとscipyをインストールします(システムのpython3にはこれらのパッケージがないことが多い)。以降はその仮想環境内で自身を再実行するだけです。

仕組み(出力を信頼・検証できるよう説明):

  • まず単語。 両方の文字起こしに現れる、ユニークな4単語のラン。オフセット = ラペル時間 - カメラ時間。クリップあたり数百の一致。最も密なクラスターを0.5秒以内に絞り込み、その中央値を採用。約0.1秒の精度。
  • 波形の精密調整。 カメラ音声の20秒チャンク(40秒未満のクリップは6秒チャンク)を300-3000 Hzのバンドパスフィルターで8 kHzに処理し、単語オフセットの±0.6秒の範囲でラペル音声と相互相関。中央値の6倍を超えるピークをカウント。20ミリ秒以内のチャンクは一致とみなす。5分を超えるクリップでは直線フィットによりオフセットとドリフトを算出。

出力されるすべての行:オフセット、一致したチャンク数、ばらつき、ドリフト。「CHECK BY EAR」とマークされたクリップ(一致チャンクが3未満)は最大0.1秒ずれている可能性があるため、Resolveで確認してください。クリップ全体で1フレームを超えるドリフトもフラグが立てられます。

5. クリップごとにラペルをスライスする

python3 <skill>/scripts/slice.py "<work>" "<SYNC_OUT>/lav-master.wav" "<SYNC_OUT>"

クリップごとに以下を書き込みます:

  • <SYNC_OUT>/<clip>_lav.wav:24ビット、ソースレート、クリップの長さにサンプル単位で一致(ラペル時間 = クリップ時間)
  • <work>/<clip>.wav(16kモノラル)と <work>/<clip>.json(スライスのWhisper文字起こし):ペーパー編集とビデオリールが読み取るファイル
  • <work>/clips.ndjson に "audio" フィールドが追加され、スライスを指す

レコーダーの開始が遅れた、またはクリップに対して早く停止した場合、その部分は無音で埋められ、警告が表示されます。スライスに対するWhisperの処理には数分かかります。その後でペーパー編集の transcribe.sh を実行しないでください(jsonが存在するためスキップされますが)。

6. クリッピングをチェックする

slice.py はスライスごとにフルスケールの0.99以上のサンプルをカウントし、最長の連続部分を出力します。数百の短いラン(数十サンプル)は、通常レコーダーのリミッターがピークをキャッチしたものであり、歪みではありません。1ミリ秒以上のランがリストされる場合、またはユーザーが音が歪んでいると言った場合のみ、_D ツインファイルから該当部分をパッチします(同じタイミング、約20 dB上げる)。

7. Resolveでタイムラインを構築する

bash .claude/skills/paper-edit/scripts/ensure_resolve.sh

<work>/sync/params.json を書き込みます:

{"project":"<Video> - YYYY-MM-DD","work":"<work>","name":"Synced - Full Talk",
 "lut":"<LUT_PATH>"}

lut はオプション。使用しない場合は省略。その後、execute_resolve_code を1回呼び出します:

PARAMS = "<work>/sync/params.json"
exec(open("<skill>/scripts/resolve_sync_timeline.py").read())

プロジェクトを作成(同名が存在すれば開く)、カメラクリップとラペルスライスをインポートし、Synced - Full Talk というタイムラインを構築:各クリップはV1にピクチャーのみ(mediaType: 1)、そのスライスはA1にサウンドのみ(mediaType: 2)、同じイン・アウトフレーム。recordFrame = タイムライン開始 + round((オフセット - 最小オフセット) * 24000/1001)。これによりクリップ間の実際のギャップが保持されます。LUTはノード1に適用。カメラのスクラッチ音声はオフに。タイムラインの解像度は、クリップが縦向きの場合は1080x1920、それ以外は1920x1080(width/height で上書き可能)。タイムライン名が既に存在する場合は、既存のものを変更せずに v2 を追加します。

ユーザーに各クリップで明確な子音(「p」や「t」)の部分をいくつかスクラブさせて確認してもらいます。これが本当のチェックです。

8. 引き継ぎ

ユーザーにタイムラインが存在すること、ステップ4のクリップごとの数値(各行に1クリップ)、フラグが立ったもの、クリッピングの判定結果を伝えます。その後、次のステップに進みます:ペーパー編集(文字起こしステップはスキップ。<work> は既にセットアップ済み)またはビデオリール。

知っておくべき事実

  • 波形相関だけでは失敗しました。 残響のある部屋でカメラマイクの平均が約-65 dBだった場合、広いウィンドウでのクリップ全体および20秒チャンクの相関は一貫性のないゴミを生成しました。単語を先にマッチさせ、その後で狭い範囲の波形を検索する方法が機能します。
  • カメラの時計はしばしば間違っています。 テストでは、カメラはレコーダーより約149秒遅れていました。一部のカメラ(例:Sony)は creation_time をUTC(末尾が Z)で書き込みますが、レコーダーのBWF time_reference はローカルタイムです。creation_time は大まかなヒントとしてのみ扱ってください。単語マッチングには必要ありません。
  • ドリフトは無視できる テストした機材では:約0.5 ms/分、21分のクリップで11 ms。タイムストレッチは不要。短いクリップでは、数秒のフィットはノイズに過ぎないため0と報告されます。
  • スクリプトの再実行により、手作業で作成したスライスと6ミリ秒以内の差で再現されました。
  • 縦向き映像: 例えばSonyで縦向きに撮影した場合、4K 23.976、回転=90の表示マトリックスで記録されます。Resolveは2160x3840として読み取り、回転修正は不要です。
  • レコーダーの例、Tascam DR-10L: 48k 24ビットモノラルBWF、15分ごとに新規ファイル、_D セーフティツインは約20 dB低い。
  • paper-edit の resolve_build.py はまだカメラファイルから音声を取得します。 ラペル撮影の場合、"audio" フィールドを読み取るようになるまで、そのタイムラインはカメラのスクラッチ音声を保持します。それまではユーザーに伝えるか、A1を _lav.wav スライスに再リンクしてください。スライス時間 = クリップ時間であるため、カットポイントは同じです。
  • Whisperは -oj -ml 1 -sow オプションで単語タイミングを取得します。

関連

  • paper-edit:ラフカット。この後に実行。
  • video-reels:clips.ndjson を読み取り。"audio" フィールドがスライスから音声を取得するよう指示します(インストールされている場合)。

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

beachyphotoandfilm-arch/video-skills

Turn raw talking-head footage into an assembled rough cut inside DaVinci Resolve. Pulls the clips off your footage drive, transcribes them locally, removes failed takes, restarts, asides and dead air, then creates a new Resolve project with two paper-edit timelines ready for your fine trim. Trigger on "paper edit", "cut my raw footage", "make a rough cut", "clean up this video", or when the user points at a folder of raw camera files for a YouTube video.

beachyphotoandfilm-arch/video-skills

Design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

beachyphotoandfilm-arch/video-skills

Render finished reels out of DaVinci Resolve, write captions in the creator's voice, attach a custom Instagram cover from reel-covers, and schedule them to Instagram, TikTok and YouTube Shorts through Metricool. Handles the Drive upload hop, collision checks against the existing calendar, and cleanup. Trigger on "schedule the reels", "post these", "put these on the calendar", or after reels are approved.

beachyphotoandfilm-arch/video-skills

Build animated brand overlays (motion graphics) for a talking-head video, timed to the speaker's exact words, plus a DaVinci Resolve import file. House style is in-scene type (text beside and behind the speaker's head) plus diagrams. Transcribes the rough cut locally, picks the moments, renders transparent .mov clips, and writes an FCPXML that drops every clip onto the timeline already in position. Trigger on "make animations for this video", "add overlays/motion graphics", "animate this", "b-roll graphics for my YouTube video", or when the user shares a rough cut and asks for graphics.

beachyphotoandfilm-arch/video-skills

Cut vertical Instagram reels out of a long-form talking-head video, hook first. Picks the strongest standalone moments from the transcript, opens each reel on its punchiest line, builds vertical timelines in DaVinci Resolve framed on the speaker's face with the LUT applied, and finishes them: a hook (a held text card, or a word-by-word "build" hook with punch-in) and burned-look captions on V3; this-or-that reels get product graphics and a comment-keyword CTA card. You trim and render, nothing to import. Trigger on "make reels", "clip this for Instagram", "cut some verticals", or after a YouTube video is cut.

beachyphotoandfilm-arch/video-skills

Design YouTube thumbnails and titles for a talking-head video. Pulls graded full-res frames out of the raw footage, renders brand-styled variants in two proven layouts, and proofs them at phone size where the click actually gets decided. Trigger on "make thumbnails", "thumbnail for this video", "title and thumbnail", or after a video is cut.

beachyphotoandfilm-arch/video-skills

Run the whole YouTube video pipeline end to end, one stage at a time, stopping for the creator's approval at every gate. Paper edit, punch-ins, reels, reel covers, scheduling the reels, overlays, thumbnail and title, then scheduling the long-form video, all through Metricool. Keeps state per video so you can stop anywhere and pick up later. Trigger on "/youtube", "let's do the whole video", "run the video pipeline", "continue the <name> video", or when handed raw footage for a YouTube video.

関連スキル