mcpField
V
video-cut

video-cut

github.com/whitetoweraiクリエイティブ・メディア1778 回インストール3 週間前に更新
リポジトリ

video-cut について

Video Cut は、未編集の長尺動画からコンパクトな初稿を作るスキルです。重要な内容を残して尺を縮める編集向けに、人が採否を決め、スクリプトで境界、無音区間、レンダリングを処理し、出力を検証します。

主な機能

  1. 01文字起こし分析に基づく採否計画
  2. 02文末や無音に合わせたカット境界
  3. 03間の除去と話速の調整
  4. 04選択区間のレンダリング
  5. 05フレーム、接続部、音声同期の確認

活用シーン

  1. 01未編集の長尺動画を短縮
  2. 02脱線や長い間の削除
  3. 03初稿動画の作成と検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/whitetowerai/cut-as-code --skill video-cut

インストール後、Claude Code で/video-cutを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/
edit_coarse.json
edit_final.json
reference/
edit_coarse.schema.md
pitfalls.md
scripts/
analyze.py
assign_speed.py
build_edit.py
check_project_protocol.py
cut_render.py
inspect_bounds.py
selfcheck_frames.py
transcribe.py
verify_cut.py
tests/
test_inspect_bounds.py

詳細

Video Cut

未編集の長尺動画を、引き締まった視聴しやすいファーストカットに仕上げます。大胆に、内容を踏まえて編集し、結果を自己検証します。何を残すかという編集上の判断は人間(モデルであるあなた)が行い、同梱スクリプトが境界の調整、無音部分の回収、メモリに配慮したレンダリング、自己チェックといった機械的な精密作業を担います。

使用するケース

  • YouTube URL またはローカルファイルの未編集動画を、より引き締まったカットにする場合。
  • 依頼内容が「半分にして」「退屈な部分をカットして」「ファーストカット/ラフカットを作って」の場合。
  • 対象外:フィラーを一語ずつ細かく削る作業、マルチカムの B ロール編集、カラー/音声の仕上げ。これらは後段の P1/P2 仕上げ工程です。このスキルは P0 で、診断を検証し、確かなカットを作成します。

依存関係

/video-understand は前提条件です。先に実行し、このスキルで再作成するのではなく、検証済みのメディア、文字起こし、分析、タイムラインを使用してください。開始前にインストール済みであることを確認してください。インストールされていない場合は、この前提条件が不足していることをユーザーに警告し、メディアの処理を始めずに停止してください。

次のツールが利用できる環境を有効にしてください(特定の conda 環境名を想定しないでください)。

  • yt-dlp(ダウンロード)、ffmpeg/ffprobe(カット/レンダリング/プローブ)が PATH 上にあること
  • faster-whisper を含む Python(CPU でも動作します:device=cpu, compute_type=int8) 最初に確認します:yt-dlp --version、ffmpeg -version、python -c "import faster_whisper"。

プロジェクトプロトコルのワークフロー

次の永続的なプロジェクトファイルを使用してください。

work/cut/edit-plan.json          # hand-authored keep/drop decisions only
work/timeline.json               # generated precision ranges + source/program mapping
review/01-cut/cut-summary.md
review/01-cut/timeline-map.png
review/01-cut/boundary-review.mp4
review/01-cut/full-proxy.mp4  # optional whole-program pacing review

各正規判断には、安定した id、action(keep または drop)、start_s、end_s、reason、意味/文字起こしに関する evidence_refs があります。判断は時系列順にしてください。V1 は、元動画クリップの並べ替えや重複に対応していません。

再度文字起こしや診断を行わず、共有のエビデンスレイヤーを再利用してください。

python skills/video-understand/scripts/transcribe.py work/cache/audio16k.wav work/understand/transcript
python skills/video-understand/scripts/analyze.py work/understand/transcript.json work/understand/analysis.json

既存の精密化スクリプトは正規プランを受け付けます。単語単位で安全な境界に拡張し、必要に応じて線形の再生速度変更を割り当てた後、共有タイムラインを生成してください。

python skills/video-cut/scripts/build_edit.py work/cut/edit-plan.json work/understand/transcript.json work/cache/edit-final.json
python skills/video-cut/scripts/assign_speed.py work/cache/edit-final.json work/understand/transcript.json
python skills/video-understand/scripts/build_timeline.py work/cache/edit-final.json work/timeline.json --fps-num SOURCE_FPS_NUM --fps-den SOURCE_FPS_DEN

work/understand/media.json の正確な有理数 FPS を使用してください。30000/1001 を 30/1 に丸めないでください。timeline-map.png と短い boundary-review.mp4 を確認してください。番組全体のテンポを確認する必要がある場合に限り、full-proxy.mp4 を生成してください。結果は cut-summary.md に記録し、オペレーションチェックレポートでそのファイルを参照してください。

必須の入力元を含めてタイムラインへの寄与を記録し、オペレーションの整数 revision を更新して、使用した理解処理のリビジョンと完全に一致する値を based_on に設定してください。

"render": {
  "kind": "timeline-transform",
  "input": "../input/original-video.mp4",
  "plan": "timeline.json"
}

共有の納品用レンダラーは、すべてのリビジョンチェックに合格した後、アクティブなシーケンスをエンコードします。

単独互換ワークフロー

以下のレガシーファイルとコマンドは、移行中も引き続きサポートされます。build_edit.py は edit_coarse.json と正規形式の decisions[] の両方を受け付けます。cut_render.py は edit_final.json と timeline.json の両方を受け付けます。このスキルの transcribe.py は ../video-understand/scripts/transcribe.py の互換ラッパーです。

中間ファイルはすべて work/ に置き、プロジェクトルートに納品してください。

work/source.mp4            # downloaded original
work/audio16k.wav          # 16k mono audio for whisper
work/transcript.json/.srt  # word-level timestamps
work/analysis.json         # diagnosis (silences/fillers/runs)
work/edit_coarse.json      # *** YOUR editorial decision (hand-written) ***
work/edit_final.json       # expanded tight render segments (generated; carries per-segment speed)
work/selfcheck/            # cut re-transcript + join frames
first_cut.mp4              # THE DELIVERABLE
first_cut_report.md        # edit + self-check report

パイプライン(6 ステップ)

1. ダウンロード

アクセス可能な最高画質と音声を取得します。デフォルトのプレイヤークライアントは失敗することがよくあります(利用不可/DRM/サインイン要求)。確実な代替手段は android クライアントです。

yt-dlp --extractor-args "youtube:player_client=android" \
       -o work/source.mp4 "<URL>"

ログインなしで取得できるのが結合済みの 360p(format 18)のみの場合は、それを受け入れ、制約を記録してください。HD DASH は DRM やログインによって制限されていることがよくあります。その後、音声を抽出します。

ffmpeg -y -i work/source.mp4 -ac 1 -ar 16000 work/audio16k.wav
2. 文字起こし(単語単位)
python scripts/transcribe.py work/audio16k.wav work/transcript [base.en]

work/transcript.json(セグメントと単語ごとの開始/終了時刻)および .srt が生成されます。 faster-whisper、CPU/int8、VAD 有効、word_timestamps=True。 英語以外の場合: 多言語モデルと --lang を指定します。例: python scripts/transcribe.py work/audio16k.wav work/transcript medium --lang zh (.en モデルは英語専用です)。まず短いサンプルで言語を確認してください。 注: Whisper は、発声された「um/uh」の大半を文字起こしから除外します。これらは文字起こしから測定できないため、フィラーの検出では、以下の語句検索と無音ギャップ分析を組み合わせてください。文字起こしテキストだけに頼らないでください。

3. 診断する(「見る」+「読む」)
python scripts/analyze.py work/transcript.json work/analysis.json

表示する情報:冒頭と末尾の無音、単語間の0.8秒以上の無音(直前の単語とともに表示)、フィラーの数、wpm、speaking_ratio、ほぼ同一の繰り返し、40秒を超える独話(冗長な話の候補)。

映像を見るには、約2秒ごとにフレームをサンプリングしてコンタクトシートにまとめ、自分で確認します。シーン構成を確かめ、黒画面や不要なフレームを探してください。

ffmpeg -y -i work/source.mp4 -vf "fps=1/2,scale=240:-1,tile=10x10" -frames:v 1 work/contact.png
ffmpeg -i work/source.mp4 -vf "blackdetect=d=0.1:pic_th=0.98" -an -f null -

単一の静的なトーキングヘッド映像ではシーンの切り替わりはありません。これは想定どおりです。また、後半のジャンプカットは通常のものであり、グリッチではないことに注意してください。

4. カットを決める — edit_coarse.json を手作業で作成する

ここが編集の中核です。文字起こしと分析を読み、タイムライン全体を隙間や重複なく敷き詰める残すブロックと削除する区間の粗いプランを作成します。それぞれに in、out、1行の reason を指定します。冗長な前置きは価値の高い要点に絞り、内容のある部分は大きなブロックとして残し、明らかな脱線や冗長な話は削除します。時系列を保ってください。標準のV1タイムラインでは並べ替えはできません。 実行時間をおおよそ半分にすることを目指します。

  • 形式の仕様と実際の詳細な例:reference/edit_coarse.schema.md。
  • すべてのブロック境界を文または節の終わりに合わせてください。文の途中や、どもりの途中で開始・停止しないでください。次を使用します。
    python scripts/inspect_bounds.py work/edit_coarse.json work/transcript.json
    
    レガシー形式の keep[] と標準形式の decisions[] のどちらのプランにも対応し、各境界をまたぐ単語を表示するので、きれいな区切りになるよう調整できます。
5. 拡張 → 自動速度調整 → レンダリング

大まかなブロックを、無音部分のない短いレンダリングセグメントに分割し、話すペースを正規化してからレンダリングします。

python scripts/build_edit.py   work/edit_coarse.json work/transcript.json work/edit_final.json 1.5
python scripts/assign_speed.py work/edit_final.json   work/transcript.json   # adds per-segment speed
python scripts/cut_render.py    work/edit_final.json   work/source.mp4 first_cut.mp4
  • build_edit.py は、各ブロックを内部の間(SPLIT_GAP、第4引数。例:1.5秒)で分割し、すべての境界を無音部分の内側にトリミングします(LEAD 0.10秒/TRAIL 0.30秒)。これにより、単語が途中で切れることなく、無音部分を回収できます。SPLIT_GAP を小さくすると、より細かくなりますが、つなぎ目がぎこちなくなります。ゆっくりと慎重に話す話者には、0.6ではなく約1.5を推奨します(細かすぎるカットを避けられます)。
  • assign_speed.py(自動の可変速再生)は、decision_ref ごとにレンダリングセグメントをグループ化し、手動で作成した各キープ判定の話すペースを測定して、共通の speed 係数と各セグメントの調整後の out_dur を edit_final.json に書き戻します。ペースが快適な範囲内であれば1.0のままです。範囲外の場合は、直近のデッドバンド端までしか調整しません。隣接する判定ブロックの差は最大0.08xに抑え、「ポンピング」のようなつなぎ目を避けます。変更するのはペースだけで、残すコンテンツは変更しません。レンダリング前に、出力された表を確認してください。
    • 指標:words/min(英語)。CJK(zh/ja/ko)では自動的にchars/minに切り替わります。
    • デフォルト値は初回実行時の出発点であり、検証済みの定数ではありません。デッドバンドは145~185 WPM、速度は1.0~1.3に制限されます。速度を上げる方向のみで、遅い判定ブロックは引き締められますが、自然に速い話し方は1.0のままです。短い判定ブロック(3.5秒未満/6語未満)は測定値のばらつきが大きいため、全体の係数を引き継ぎます。
    • 速度は無音部分の回収後に測定されるため、実際のWPMより高く表示され、調音速度に近い値になります。出力された表の確認は不可欠です。表を目視で確認し、レンダリング前に話者に合わせて deadband を調整してください。デフォルト値を確認せずに信頼しないでください。
    • 調整項目(k=v):mode=segment|global|off(デフォルトは segment。global は動画全体に1つの係数を適用し、off は無効化します)、deadband=lo,hi、min_speed=/max_speed=、min_seg=/min_words=、lang=auto|en|cjk。この機能を完全にスキップするには、この手順を実行しないでください。cut_render.py は speed がない場合、1.0として扱います。
  • cut_render.py は、シーク付きの入力をN個用意し、concatフィルターで連結して1回だけ再エンコードします。これは必須です。1つのデコード済み入力に対してN回トリミングすると、ffmpeg はデコード済みのストリーム全体をバッファーします(長い動画では数十GBになります)。reference/pitfalls.md を参照してください。セグメントに speed が設定されている場合、各入力のタイミングを調整し(映像は setpts、音声は atempo)、連結前に入力ごとにfps/タイムベース/サンプルレートを正規化して、音声と映像の同期を保ちます。speed がなければ、元のグラフをそのまま使用します。
  • 最終比較:video-edit-compare は、正規タイムラインと実際の最終納品物を読み込みます。最終映像のピクセルをソースの時間軸に投影し、可変速クリップをソースの長さに引き伸ばして、削除された範囲を黒く表示します。
6. セルフチェック — これに合格するまで完了と宣言しないでください
# protocol precision regression check (run from the repository root)
python skills/video-cut/scripts/check_project_protocol.py
# re-transcribe the finished cut
ffmpeg -y -i first_cut.mp4 -ac 1 -ar 16000 work/selfcheck/cut_audio16k.wav
python scripts/transcribe.py work/selfcheck/cut_audio16k.wav work/selfcheck/cut_transcript
# content + filler + boundary check
python scripts/verify_cut.py work/edit_final.json work/transcript.json work/selfcheck/cut_transcript.json
# frame / black / join check (join times use post-speed out_dur, so they stay accurate)
python scripts/selfcheck_frames.py work/edit_final.json first_cut.mp4 work/selfcheck
# A/V sync + no residual dead air
ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffprobe -v error -select_streams a:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffmpeg -i first_cut.mp4 -af silencedetect=noise=-32dB:d=1.5 -f null -

合格基準:

チェック項目合格条件
黒フレームなし
つなぎ目のフレームクリーンであること — 自然な頭の動きのみで、黒フレーム/フリーズ/破損がない
音声と映像の同期映像と音声の長さの差が約1フレーム(約30ms)以内であること。可変速再生が有効な場合、合計はおよそ final_duration_s_after_speed であること
1.5秒以上の無音0(speaking_ratio が大幅に上昇していること)
セグメントの欠落/重複なし — 重要な内容がすべて含まれていること(difflib が約0.90なら問題ありません。これより低い場合、通常は内容の欠落ではなく、もごもごした発話を2回目に文字起こしした際のノイズです。カットを疑う前に、キーワードが含まれているか確認してください)
文の途中での切断なし — 境界が無音部分または文末にあること

**フィラーに関する正直な但し書き:**段落単位のカットでは、「フィラーをほとんどなくす」ことはできません。残した内容が会話調であるため、1分あたりの密度が上がることさえあります。この点は正直に報告してください。単語単位のフィラー削除はP1/P2で行います(1ショットのトーク映像では、映像が目に見えてぎこちなくなります)。

最後に

first_cut_report.md を作成します。内容は、ソースの概要、カットした箇所とその理由、セルフチェック表、 および正直な注意点(360p のソースによる品質の上限、フィラーの密度など)です。 可変速を適用した場合は、その旨を明記します。読者がカットが実時間と 1 対 1 ではないことを把握できるよう、 再タイミングしたセグメント数と速度の範囲(assign_speed.py の表/speed_params に基づく)を記載します。 また、速度を上げると verify_cut.py の 1 分あたりのフィラー数がわずかに高く表示されることにも触れます(同じ語数で分数が短くなるための報告上の差異であり、フィラーが追加されたわけではありません)。

重要な原則(苦労して得た教訓)

  • 内容は自分で決め、スクリプトにはフレームを決めさせます。 edit_coarse.json は手書きし、 精密な調整は build_edit.py に、ペース調整は assign_speed.py に任せます。
  • 速度調整が変えるのはペースだけで、内容には触れません。 自動可変速では、同じ decision_ref から生成されたすべてのレンダーセグメントに同じ速度を適用し、許容範囲を外れたペースは最も近いデッドバンドの境界までしか調整せず、隣接する判断の差を 0.08x 以内に制限し、出力を 1.0~1.3 に収めます。 atempo はピッチを維持します。表を確認してください。無効にするには mode=off にするか、この手順を省略します。
  • 単語を決して途中で切りません。 境界は必ず無音部分に置きます。
  • メモリセーフなレンダーのみを使用します(N 個のシーク済み入力+連結)。1 つの入力に複数のトリムを適用してはいけません。
  • 迷わず決断します。 妥当な判断をして、作業を進めます。質問しすぎないでください。
  • セルフチェックは必須です。 完了とする前に、再度文字起こしを行い、フレームをチェックします。
  • 注意点と対処法の全一覧は reference/pitfalls.md を参照してください。

コメント