mk-video-editing は何をしますか?
提供された映像を、見やすく一貫性のある編集成果物に仕上げます。適切な順序で正しい言葉が並び、被写体をうまくフレーミングするカメラ、一貫した画質、クリーンでレベルが合った音声、そしてセンスの良いタイトルを実現します。構成は映像そのものと、その中で語られる内容から生まれます。
このスキルでできること
| ニーズ | ツール | コスト | 参考 |
|---|---|---|---|
| 文字起こし、フィラー/言い直し/間の検出 | edit:transcribe (mlx-whisper), speech:flow | 無料、ローカル | footage-editing.md |
| 手ぶれ補正、話者の追跡、4Kワイドのリフレーミング(プッシュ、パンチイン、パン)、HDR→SDR、デフリッカー、カラーマッチ、ディゾルブ、ジャンプカット | edit:analyze, edit:track, EDL + medit (edit:render) | 無料、ローカル | footage-editing.md |
| ダイアログのクリーンアップ、ミックス、ダッキング、ラウドネス調整 | speech:clean (ISOLATE=1 Demucs), speech:mix, speech:measure | 無料、ローカル | footage-editing.md |
| ナレーション | voice:tts (Fal経由のElevenLabs) | 有料、承認済み | credentials.md |
| タイトル、ローワーサード、エンドカード(ProRes 4444 アルファチャンネル) | mgraphics JSONシーン、graphics:render、scripts/tools/graphics/examples/のテンプレート | 無料、ローカル | graphics README |
| BGM | EDL music(ダッキング)、music:score(Fal経由のElevenLabs Music)、ビートタイミング用 audio:analyze | 生成時のみ有料 | finishing.md |
| タイトル/トランジションの効果音 | SoundSynth (synth: シューッ、ライザー、インパクト、チック…)、 sfx:gen/sfx:mix または EDL sounds | 無料(Stable Audio prompt: は有料) | finishing.md |
| ピクチャーエフェクト(フラッシュ、ディップ、パンチ、グロウ、レンズ、ストリーク…) | mvfx キューシート、vfx:stills/vfx:render | 無料、ローカル | finishing.md |
| 納品用エンコード | media:twitter, media:youtube, media:faststart | 無料、ローカル | tasks.md |
| 独立したジョブの並列サブエージェント | work:next/work:accept/work:log/work:watch | 無料 | tasks.md |
すべてのタスクとその引数・オプションは tasks.md にあります。テストプロファイルは testing.md にあります。
実行契約
macOS 14+、Apple Silicon(Swift 5.9+、Ruby 3.2+、Bundler、FFmpeg、ImageMagick、ローカルWhisper用uv)上のClaude Code向けに設計されています。タスクがツール不足で失敗した場合は、まず doctor を実行します。setup でSwiftツールをビルドします。Rubyが唯一の実行エントリレイヤーです:ruby "${CLAUDE_SKILL_DIR}/scripts/mv.rb" --project /abs/project 'task[args]' を実行します。タスクはRubyサービス(lib/media/edit.rb、speech.rb、guard.rb、…)に委譲され、それらがネイティブSwiftツール medit(scripts/tools/edit)、mgraphics(scripts/tools/graphics)、mvfx(scripts/tools/vfx)を駆動します。機能が不足している場合は、Rubyメソッドと簡易タスクを追加します。プロジェクトは 自身のコピー の lib/ と tools/ を保持します。スキルを変更した後は、変更されたファイルをプロジェクトに rsync します。
メモリ安全性(必須)
4K/HDRハードウェアデコードはフレームを VTDecoderXPCService に保持し、ジョブ自身のフットプリント外に置きます。スワップがない16GBマシンでは、メモリを使い果たすと処理が遅くなる代わりに コンピュータがフリーズします。そのため:
- 一度に実行する重いジョブは一つだけ(medit analyze/render/stills、mgraphicsエンコード、Demucs、大規模ffmpegエンコード)。これらを並列またはバックグラウンドで同時に起動しないでください。必要であれば、一つのバックグラウンドコマンド内で逐次的にチェーンします。
JOBSはRAMが32GB以上でない限り1のままにします。 - medit/mgraphics/mvfxのすべてのレンダリング呼び出しは、
Media::Guard(Rubyサービスで自動的に使用)を通過します。これは0.3秒ごとにジョブ+デコーダのフットプリントとカーネルの空きメモリ割合をサンプリングし、MEDIT_MAX_FOOTPRINT_MB(デフォルト3500)を超える前、またはMEDIT_MIN_FREE_PCT(デフォルト30)を下回る前にSIGKILLを発行します。空きメモリが既に少ない場合は起動を拒否します。3つのレンダラーはすべてデフォルトでJOBS=1になります。並列チャンクには明示的なJOBS設定が必要です。 - 新しいデコード/レンダリングコードパスは、最初に狭い範囲と厳しい制限で検証します(
TO=15 MEDIT_MAX_FOOTPRINT_MB=1500 MEDIT_GUARD_LOG=/path/log)。ログが平坦であることを確認してから、フルレングスで実行します。 - Swiftメディアループでは、各
copyNextSampleBufferとCore Imageレンダリングをautoreleasepoolでラップします(非同期コードはデフォルトプールをドレインせず、フレームが約1.5GB/sでリークします)。
測定された定常状態:分析は4K HLGソースあたり約1.0GB(ジョブ+デコーダ)。ディゾルブを含むレンダリングでは2つのソースを開きます。
1. 取り込み(Intake)
不足している情報のみを尋ねます:映像ファイルのパス、編集内容(トークの抜粋、まとめ…)、タイトル/クレジットのテキスト、目標尺、ナレーションの要望。メディアを初期化します(シンボリックリンク。コピーや変更は絶対に行いません):
ruby "${CLAUDE_SKILL_DIR}/scripts/mv.rb" init --project /abs/project --media /abs/clip1.MOV --media /abs/clip2.MOV --prompt-file /abs/brief.md
ruby "${CLAUDE_SKILL_DIR}/scripts/mv.rb" --project /abs/project setup
各ソースをプローブします(ffprobe:サイズ、fps、長さ、HDR転送特性)。オーディオを抽出し(audio/raw/*.wav、48 kHz)、ローカルで文字起こしを行います:edit:transcribe[analysis/transcripts,source/...](mlx-whisper large-v3-turbo、ワードタイム付き、無料)。すべてのトランスクリプトを読み、各クリップの発言内容をタイムスタンプ付きで docs/BRIEF.md に書き出します。タイトルで使用するイベントの事実をウェブ検索し、ソースを記録します。
2. 分析(Analyze、逐次実行)
REGION=0,0,1,0.62 DETECT_REGION=0.15,0.3,0.85,0.8 mv 'edit:analyze[source/A.MOV,analysis/A.json]' # 一つずつ実行
mv 'edit:track[analysis/A.json,analysis/A.track.json]' # 話者が早期に見つからない場合 SEED=x,y;手ぶれ補正用 SPACE=frame: 0
mv 'edit:stats[analysis/A.json,from,to]'
REGIONは手ぶれ補正(位相相関)を静的な風景(ステージ、スクリーン)に制限し、観客を除外します。DETECT_REGIONはVision人物検出用にステージ領域を約2倍の解像度でクロップします。遠くの話者に不可欠です(検出率がサンプルの2%から40〜90%に向上)。- トラックはワールドロック(手ぶれ補正除去)され、連続性が選択され、
max_aspectによって広い前景ボックス(頭部分)をドロップします。 - スマートフォン映像(iPhoneなど)はカメラ内で既に手ぶれ補正されています:
stabilize: 0とSPACE=frameトラックでレンダリングします。 私たちの手ぶれ補正は、動いているスライドコンテンツをカメラの動きと誤認し、突然の水平ジャンプを追加する可能性があります。確認方法:分析内で|Δshift| > 8 pxのフレーム数をカウントします。iPhone 4Kでの残留ブレは約0.9 px RMSと測定されており、補正する価値はありません。
発話フロー(フィラー、言い直し、繰り返し、不自然な間)
VERBATIM=1 mv 'edit:transcribe[analysis/transcripts_verbatim,source/A.MOV]' # Whisperに「えーと」「あのー」を書き起こさせる
mv 'speech:flow[analysis/transcripts_verbatim/A.json,audio/clean/A.wav,analysis/flow/A.json]' # analysis/flow/A.txt を読む
検出器は間を音響的に測定し(Whisperのワードタイムではなく、エネルギー+有声性)、分類し(文/コンマ/フレーズ)、フィラー、書き起こされないうめき声、繰り返し、可能性のある言い直しをフラグします。それぞれに提案 cut が付与されます。意味に基づいてそれぞれを判断し、ジェネレーター(ステップ4)で Media::Cuts を使用してカットを適用します。自己修正や放棄された文(「そのためには—」、拍手前の未完了の最後の文など)を .txt を読んで見つけてください。検出器は候補を提案するだけです。
- 全フレームのカラーステータスはプロジェクションスクリーンによって支配されます。トラック周辺のタイル(話者エリア)で露出を合わせ、静止画でホワイトバランスを判断します。
3. 計画と承認(Plan and approve)
docs/PLAN.md を書きます:セレクト表(ソース、文の境界でのイン/アウト、内容、結合:ディゾルブ/ジャンプカット)、タイトル、ナレーションテキスト、カメラ言語、ピクチャーおよびオーディオ処理。チャットで要約し、NOTE='...' plan:approve で承認を記録します(有料API呼び出し前にも必要です。例:voice:tts 経由のElevenLabsナレーション。credentials.md を参照 — プラグインセッションでは、有料タスクは mk-video-editing MCPサーバーを介して実行されます)。
4. ジェネレータースクリプトでEDLを構築(Build the EDL with a generator script)
edit/build_edl.rb を書きます(完全なEDLスキーマと実例については footage-editing.md を参照)。ショット語彙を定義し(WIDE ズーム≈1.2–1.4、MWIDE フィット≈0.4、MED フィット≈0.56、PUNCH フィット≈0.72、max_zoom 3.6で制限)、トランスクリプトから取得した ソース秒単位 でカメラのビートを記述します:6〜12秒かけてのスロープッシュ、強調線でのカットパンチイン、トピック/スライド変更時のワイドへのカット、ジャンプカットごとのリフレーミング。クリップごとに:safe エリア(気を散らす前景を除外)、deflicker、grade マッチ。一つの共有 look。オーバーレイはProRes 4444アルファタイトルです(下記のタイトルを参照)。
lib/media/cuts.rb を使用してセレクト内の単語と間を削除します:Media::Cuts.pause_cuts(不自然な間を自動短縮)、Media::Cuts.segments(セレクトをジャンプカットセグメントに分割、境界を単語間の最も静かなポイントにスナップ、各セグメントを対照的なフレーミングで開始、各ズームを4.5秒以上に維持)、Media::Cuts.text(各カットで削除される内容を edit/cuts.txt に記録)。各セレクトは無音で開始・終了し、カメラ操作の付近を避けます(端付近のシフト速度を確認)。実例は footage-editing.md にあります。
5. オーディオ(Audio)
speech:clean[audio/raw/A.wav,audio/clean/A.wav](PRESET=room:ランブルカット、FFTノイズ除去、マッドカット、プレゼンス、デエッサー、穏やかなエキスパンダー、レベル調整。ISOLATE=1 でローカルDemucsボーカル抽出)。リクエストがあれば voice:tts でナレーションを追加します(MODEL=v4 はEleven v4)。ブリーフで要求されている場合にのみBGMを追加します:提供されたトラックまたは music:score をEDL music として配置します(finishing.md)。その後、speech:mix[edit/edl.json,audio/mix.wav] を実行します。クリップオーディオをディゾルブ上のクロスフェードでミックスし(audio_xfade: 0.15 は0.6秒のディゾルブの前に最後の単語を保持)、ナレーション中は audio_duck、sounds、music にサイドチェインダッキングを適用し、その後2パスの loudnorm を −16 LUFS / −1.5 dBTP に適用します。
6. レビュー、レンダリング、納品(Review, render, deliver)
DEBUG=1 edit:stills[edit/edl.json,edit/review/vN,t1,t2,...]— 各静止画と、クロップ(赤)、被写体(緑)、セーフエリア(黄)を含むフルソースフレームを生成。フレーミング、ヘッドルーム、前景の侵入、カット間の露出/WBの連続性を確認します。edit:sheetコンタクトシート。edit:preview[edl,out.mp4,from,to]変更範囲のハーフレゾ draft。edit:render[edit/edl.json,output/final.mp4](JOBS=1)。納品済みのマスターを決して上書きしないでください。- ビデオレンダリング前のQA:
speech:mixを実行し、次にミックスをedit:transcribeし、各クリップのat付近の単語を読みます(安価で、クリップされた単語や一瞬のフラッシュをキャッチします)。レンダリング後、最終版を再度文字起こしします。バージョンと問題をdocs/REVIEW.mdに記録します。
動画、計画/ブリーフ/レビュー文書、および選択内容と既知の問題の短い要約を納品します。ツールキットを変更した後は testing.md からRSpecプロファイルを実行し、レンダラーを変更した後は tools/graphics で swift test を実行します。
タイトル(Titles)
scripts/tools/graphics/examples/ のテンプレートから始めます:opening_title.json、lower_third.json、end_card.json(1920×1080、AvenirNext、一つのアクセントカラー)。これらを edit/titles/ にコピーし、テキストとタイミングを変更するか、複数ある場合は edit/make_titles.rb から生成します。名前、役割、イベントの事実をウェブ確認します。
ONLY=を使用して、ショットのフレーム上で静止画をレンダリングし(PLATE=)、可読性、セーフマージン、アクセントを確認します。CODEC=prores4444 SUPERSAMPLE=2 graphics:render[edit/titles/x.json,edit/titles/x.mov,frames,1920,1080,fps]を編集のfpsでレンダリングします。- それを EDL
overlaysエントリとして配置し、開始カードの下のプレートをカメラdim/blurで暗くするかぼかします。
シーンフォーマット(ノード、トラック、イージング、グロー、フォント)については graphics README を参照してください。レンダラーを変更した後は、scripts/tools/graphics で swift test を実行し、新旧のタイトルレンダリングをバイト単位で比較します。
仕上げ(Finishing、オプション)
BGM、効果音、ピクチャーエフェクトはオプションのパスであり、finishing.md で説明されています:
- BGMはレンダリング前に
speech:mixに組み込まれます。 - SFX(
sfx.yml)とVFX(cues.yml)はレンダリング済みマスターに対して実行され、常に新しいファイルを書き出します。
プロモーションやまとめ風の雰囲気がブリーフで要求されている場合に使用します。クリーンなトーク編集ではこれらが必要になることはほとんどありません。
並列作業(Parallel work)
長い編集の場合、独立したジョブ(タイトル、ナレーション行、セクションごとのレビュー静止画、QAトランスクリプト)を config/production.json に depends 付きで分割します。これらを work:next でサブエージェントに渡し、work:log で報告させ、レビュー後に work:accept で受け入れます。サブエージェントはシーン、スクリプト、ドキュメントを並行して作成できます。重いメディアジョブ(medit、mgraphics/mvfxエンコード、Demucs)は依然として一度に一つだけ実行します(上記のメモリ安全性のため)。