clipify
ビデオから最も面白い瞬間を検出し、スタンドアロンクリップとしてカットできます。オプションで16:9から9:16へのリフォーマット(フェイスパンまたはスプリットスクリーン)に対応し、Opus風の単語ごとのキャプションを焼き込みます。ユーザーが「clipify」「このビデオからクリップをカットして」「これからショーツを作って」「面白い瞬間を見つけて」「9:16にリフレーミングして」「縦型クリップ」と言及したり、ビデオファイルパスを貼り付けてSNS対応のクリップを求める場合に使用します。
description の原文を見る
Find the funniest moments in a video, cut them as standalone clips, optionally reformat 16:9 → 9:16 (face-pan or split-screen), and burn opus-style word-by-word captions. Use when the user mentions "clipify," "cut clips from this video," "make shorts from this," "find funny moments," "reframe to 9:16," "vertical clips," or pastes a video file path and wants social-ready cuts.
SKILL.md 本文
Clipify
動画の中で最も面白い瞬間を見つけ、スタンドアロンのクリップとしてカットし、必要に応じて 16:9 → 9:16 にリフォーマット(フェースパンまたはスプリットスクリーン)し、Opus スタイルのワードバイワードキャプションを焼き込みます。
入力
- ビデオファイルパス(ユーザーが提供します。ない場合は尋ねます)
- オプション: リクエストされたフォーマット(9:16、16:9、1:1) — 指定されていない場合は、候補を選んだ後に尋ねます
- オプション: サブタイトルスタイルの好み — 指定されていない場合は、キャプション追加前に尋ねます
ツール(最速パスのみ使用)
- Whisper:
whisper --model tiny.en --word_timestamps True --output_format json(約 10 倍高速、品質は英語には問題なし)。非英語の場合:--model base(--languageは削除) - ffmpeg: デコードに
-hwaccel videotoolboxを追加し、レンダリングに-preset ultrafastを追加します。最終マスターには-c:v libx264 -crf 20を使用します。 - Numpy オーディオアライメント用(FFT 相互相関)。scipy/cv2 は不要です。
- スクリプト:
<skill-dir>/scripts/(<skill-dir>はこの SKILL.md を含むディレクトリ — 通常は~/.claude/skills/clipify/)analyze.py— 2 つの ROI モーションファイルからスピーカータイムラインbuild_pan.py— ffmpeg クロップ x 式とハードカットbuild_ass.py— Whisper JSON から Opus スタイルの ASS キャプションaudio_align.py— 長いソースでのサブクリップのオフセット検出
作業ディレクトリ: /tmp/clipify/ (開始時に mkdir し、デバッグ用に成果物を残します)
ワークフロー
ステップ 1 — 最も面白い部分を見つける
mkdir -p /tmp/clipify
ffmpeg -y -hwaccel videotoolbox -i "$VIDEO" -vn -ac 1 -ar 16000 /tmp/clipify/audio.wav
whisper /tmp/clipify/audio.wav --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en
結果の JSON(または .txt)を読み、3〜5 個の候補クリップを選びます。面白さの信号をスキャンします:
- パンチラインとリアクション: 「what」「wait」「no way」「laughter」「haha」「swearing」などの単語
- 反転の瞬間: セットアップの質問 → 予期しない答え
- 気まずい沈黙: Whisper セグメントに長いギャップがある、またはフィラー(「uh」「um」)
- セルフロースト / 名台詞: スタンドアロンで成立する短い叙述文
- オーディオピーク:
ffmpeg -af volumedetectで検出、または急速な応答(Whisper セグメントが短く交互)を探す
各候補について、以下を提案します: [開始、終了、なぜ面白いのか、推奨タイトル]。10〜25 秒のクリップを目指します。リストを表示し、ユーザーに確認/選択させます。
ステップ 2 — 選んだ各クリップをトリム
ffmpeg -y -ss "$START" -t "$DURATION" -i "$VIDEO" -c copy /tmp/clipify/clip_$N.mp4
(-c copy を使用して即座にトリムします。カットがフレームアキュレートである必要がある場合のみ再エンコードします)
ステップ 3 — 出力フォーマットを決定
ユーザーに尋ねます(すでに指定されている場合はスキップ): 「9:16(TikTok / Reels)、16:9(YouTube)、1:1(Insta フィード)?」
ステップ 4 — 16:9 → 9:16 の場合: フェースパン vs スプリットスクリーン
ffprobe でソースアスペクト比を検出します。ソースが 16:9 でターゲットが 9:16 の場合、尋ねます:
「2 つのオプション: (a) 話している人を追う hard-cut パン(一度に 1 つの顔のみ画面に表示)、または (b) スプリットスクリーン両方の顔が見える積み重ね。どちらを希望しますか?」
顔が 1 つだけ(シングルトーカークリップ)の場合、質問をスキップします。シングルトーカーの場合は、単に中央クロップします。
ステップ 4a — フェースパン(高速カット会話型トーキングヘッド対話に推奨)
-
2 つの顔 ROI を特定します。 1 フレームをサンプリング:
ffmpeg -ss <middle> -i <clip> -frames:v 1 /tmp/clipify/probe.jpg。それを読みます。ソースのピクセル空間で各顔の口+顎の領域をx,y,w,hとして目測します(cv2 は不要 — カメラはクリップ内で静止、1 フレームで十分)。ボックスを描画して確認します:ffmpeg -i probe.jpg -vf "drawbox=x=$LX:y=$LY:w=$LW:h=$LH:color=cyan@0.9:t=4,drawbox=x=$RX:y=$RY:w=$RW:h=$RH:color=magenta@0.9:t=4" verify.jpg最大 2 回 反復します。ボックスは口 + 顎をカバーし、手/マイクを避けるべきです。過度にチューニングしないでください — フレーム差分は許容度が高いです。
-
各 ROI でフレームごとのモーションエネルギーを抽出します:
ffmpeg -y -i clip.mp4 -filter_complex " [0:v]split=2[a][b]; [a]crop=$LW:$LH:$LX:$LY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/L.txt[la]; [b]crop=$RW:$RH:$RX:$RY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/R.txt[ra] " -map "[la]" -f null - -map "[ra]" -f null - -
スピーカータイムラインを構築します(最小滞在時間 1.0 秒 — 短い割り込みは前のスピーカーにマージされます):
python3 <skill-dir>/scripts/analyze.py /tmp/clipify/L.txt /tmp/clipify/R.txt 1.0 > /tmp/clipify/segments.json -
ソースから 9:16 の垂直ストリップのパン x 座標を選択します。 ソース W=1920、ターゲット W=1080 の場合、クロップストリップ幅 = 608。
- LEFT_X =
face_left_center_x - 304(≥ 0 でクランプ) - RIGHT_X =
face_right_center_x - 304(≤ source_W - 608 でクランプ)
- LEFT_X =
-
hard-cut x 式を生成してレンダリングします:
EXPR=$(python3 <skill-dir>/scripts/build_pan.py /tmp/clipify/segments.json $LEFT_X $RIGHT_X) ffmpeg -y -hwaccel videotoolbox -i clip.mp4 -filter_complex \ "[0:v]crop=608:1080:x='$EXPR':y=0,scale=1080:1920:flags=lanczos[v]" \ -map "[v]" -map 0:a -c:v libx264 -preset fast -crf 20 -pix_fmt yuv420p \ -c:a aac -b:a 192k /tmp/clipify/clip_panned.mp4ソース 1920×1080 を想定。4K ソースの場合は、最初にダウンスケールするか、すべての座標を 2 倍にします。
ステップ 4b — スプリットスクリーン(常に両方の顔が見える)
2 つの積み重ねたタイル、各 1080×960。アクティブなスピーカーのタイルが上にあり — スピーカー変更時にオーバーレイが反転します。
[0:v]split=2[a0][a1];
[a0]crop=Wcrop:Hcrop:LX_tile:LY_tile,scale=1080:960,split=2[lt0][lt1];
[a1]crop=Wcrop:Hcrop:RX_tile:RY_tile,scale=1080:960,split=2[rt0][rt1];
[lt0][rt0]vstack[layoutL];
[rt1][lt1]vstack[layoutR];
[layoutL][layoutR]overlay=0:0:enable='<RIGHT_SPEAKER_ENABLE>'[v]
segments.json から <RIGHT_SPEAKER_ENABLE> を between(t,a,b)+between(t,a,b)+... として右スピーカーセグメント上に構築します。タイルクロップは各顔の周囲 ~720×640 をターゲットにします(1080×960 に合わせるために 1.125:1)。
ステップ 5 — サブタイトルを追加
一度尋ねます(ユーザーがすでにスタイルを指定していない場合のみ):
「3 つのサブタイトルスタイル: opus(大きな太字の白、黄色のアクティブワードハイライト)、karaoke(4 ワードチャンク、緑のハイライト)、minimal(クリーンな Helvetica、ハイライトなし)。または、好きな例を貼り付けてください。」
参照画像/例を貼り付けた場合: フォント、サイズ、ウェイト、色、位置、アニメーションをできるだけ一致させます — カスタム ASS を手書きするか、build_ass.py を拡張します。
そうでない場合はプリセットを使用します:
# トリムされたクリップで whisper を再実行し、クリップ開始を基準とした正確なタイムスタンプを得ます
whisper /tmp/clipify/clip_panned.mp4 --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en
python3 <skill-dir>/scripts/build_ass.py /tmp/clipify/clip_panned.json /tmp/clipify/captions.ass opus
キャプションを焼き込みます:
ffmpeg -y -i /tmp/clipify/clip_panned.mp4 -vf "subtitles=/tmp/clipify/captions.ass" \
-c:v libx264 -preset fast -crf 20 -c:a copy "$OUTPUT.mp4"
ステップ 6 — 配信
- 各出力を
<source_dir>/clipify_out/に保存(ない場合は mkdir) - クリップごと 1 行を出力: 名前、期間、何が面白かったのか、出力パス
open <path>で最初の出力を開き、ユーザーが確認できるようにします- 反復を提案(異なるスタイル、異なる ROI、スプリットスクリーンに切り替え、キャプションの時間を調整)
落とし穴(以前の実行からの教訓 — 繰り返さないでください)
- ROI を過度にチューニングしないでください。 最大 2 回の反復。モーション差分は許容度が高く — 口+顎をカバーするより広い ROI は、完全に口中心でなくても問題なく機能します。
- クリップ内のシーンカットに注意してください。
ffmpeg -filter:v "select='gt(scene,0.3)',showinfo" -f null -を実行してカットをカウントします。16:9→9:16 クリップに多くのカットがある場合、固定顔 ROI は支配的なシーンにのみ機能します。ユーザーに警告し、シングルテイククリップを選択するか、カット中のオフセンタースレーミングを受け入れるか、いずれかを提案します。 - ソース解像度は重要です。 ソースが 4K の場合、最初に 1920×1080 にダウンスケール(高速、9:16 出力に問題なし)するか、すべての ROI/パン座標に 2 を掛けます。
- ソースの焼き込まれたサブタイトル。 一部の「ロー」クリップにはまだサブタイトルがあります。その場合は、オーディオ相互相関(
audio_align.py)を経由してノーサブマスターを見つけ、そこからトリムします。 - 短いクリップで十分な場合は、フル長ソースで whisper を実行しないでください。 ステップ 2 の後にトリムされたクリップで Whisper を実行します。面白い瞬間を見つけるためにトランスクリプトが必要な場合のみ、ステップ 1 でフルソースで whisper を実行します。
- 計画を 1 行で述べてから実行します。 反復のたびにナレーションしないでください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- louisedesadeleer
- ライセンス
- MIT
- 最終更新
- 2026/5/5
Source: https://github.com/louisedesadeleer/clipify / ライセンス: MIT