clip-hand-skill について
clip-hand-skillは、動画のダウンロード、文字起こし、編集を行うクリエイター向けの動画処理ガイドです。字幕作成、画面調整、音声処理、各OSでのコマンドライン操作を扱います。
主な機能
- 01yt-dlpによる動画取得とメタデータ確認
- 02Whisper文字起こしと単語単位の時刻
- 03SRT・ASS字幕の生成
- 04FFmpegによる切り出し・画面調整・字幕焼き込み
- 05サムネイル作成とシーン分析
活用シーン
- 01オンライン動画からクリップを抽出
- 02動画字幕を作成して埋め込み
- 03縦型ショート動画を作成
- 04無音区間やシーン切り替えを分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rightnow-ai/ openfang --skill clip-hand-skillインストール後、Claude Code で/clip-hand-skillを入力して読み込まれたか確認します。
同梱ファイルHAND.toml
詳細
動画クリッピングの専門知識
クロスプラットフォームに関する注意事項
すべてのツール(ffmpeg、ffprobe、yt-dlp、whisper)では、Windows、macOS、Linux で同一の CLI フラグを使用します。違いはシェル構文のみです。
| 機能 | macOS / Linux | Windows (cmd.exe) |
|---|---|---|
| stderr を抑制 | 2>/dev/null | 2>NUL |
| 出力をフィルタリング | | grep pattern | | findstr pattern |
| ファイルを削除 | rm file1 file2 | del file1 file2 |
| null 出力デバイス | -f null - | -f null -(同じ) |
| ffmpeg の字幕パス | subtitles=clip.srt | subtitles=clip.srt(相対パスは可、絶対パスでは C\\:/path が必要) |
重要:ffmpeg のフィルターパス(-vf "subtitles=...")では、常にスラッシュを使用する必要があります。Windows で絶対パスを指定する場合は、コロンをエスケープしてください:subtitles=C\\:/Users/me/clip.srt
SRT/テキストファイルの作成には、シェルの echo/heredoc ではなく file_write ツールを使用してください。
yt-dlp リファレンス
フォーマットを選択してダウンロード
# Best video up to 1080p + best audio, merged
yt-dlp -f "bv[height<=1080]+ba/b[height<=1080]" --restrict-filenames -o "source.%(ext)s" "URL"
# 720p max (smaller, faster)
yt-dlp -f "bv[height<=720]+ba/b[height<=720]" --restrict-filenames -o "source.%(ext)s" "URL"
# Audio only (for transcription-only workflows)
yt-dlp -x --audio-format wav --restrict-filenames -o "audio.%(ext)s" "URL"
メタデータの確認
# Get full metadata as JSON (duration, title, chapters, available subs)
yt-dlp --dump-json "URL"
# Key fields: duration, title, description, chapters, subtitles, automatic_captions
YouTube の自動字幕
# Download auto-generated subtitles in json3 format (word-level timing)
yt-dlp --write-auto-subs --sub-lang en --sub-format json3 --skip-download --restrict-filenames -o "source" "URL"
# Download manual subtitles if available
yt-dlp --write-subs --sub-lang en --sub-format srt --skip-download --restrict-filenames -o "source" "URL"
# List available subtitle languages
yt-dlp --list-subs "URL"
便利なフラグ
--restrict-filenames— 安全な ASCII ファイル名(スペースや特殊文字なし) — すべてのプラットフォームで重要--no-playlist— URL がプレイリスト内にあっても、動画を 1 本だけダウンロード-o "template.%(ext)s"— 出力テンプレート(%(ext)s はフォーマットを自動検出)--cookies-from-browser chrome— 年齢制限のあるコンテンツにブラウザーの Cookie を使用--extract-audio/-x— 音声のみを抽出--audio-format wav— 音声を wav に変換(whisper 用)
Whisper の文字起こしリファレンス
Whisper 用の音声抽出
# Extract mono 16kHz WAV (whisper's preferred input format)
ffmpeg -i source.mp4 -vn -ar 16000 -ac 1 -y audio.wav
基本的な文字起こし
# Standard transcription with word-level timestamps
whisper audio.wav --model small --output_format json --word_timestamps true --language en
# Faster alternative (same flags, 4x speed)
whisper-ctranslate2 audio.wav --model small --output_format json --word_timestamps true --language en
モデルサイズ
| モデル | VRAM | 速度 | 品質 | 用途 |
|---|---|---|---|---|
| tiny | ~1GB | 最速 | 粗い | クイックプレビュー、パイプラインのテスト |
| base | ~1GB | 高速 | 良好 | 短いクリップ、明瞭な音声 |
| small | ~2GB | 良好 | 良好 | デフォルト — 最適なバランス |
| medium | ~5GB | 低速 | より良い | 重要なコンテンツ、アクセントのある音声 |
| large-v3 | ~10GB | 最も低速 | 最高 | 最終制作、多言語 |
注:macOS の Apple Silicon では、より高速なネイティブ代替手段として mlx-whisper を検討してください。
JSON 出力構造
{
"text": "full transcript text...",
"segments": [
{
"id": 0,
"start": 0.0,
"end": 4.52,
"text": " Hello everyone, welcome back.",
"words": [
{"word": " Hello", "start": 0.0, "end": 0.32, "probability": 0.95},
{"word": " everyone,", "start": 0.32, "end": 0.78, "probability": 0.91},
{"word": " welcome", "start": 0.78, "end": 1.14, "probability": 0.98},
{"word": " back.", "start": 1.14, "end": 1.52, "probability": 0.97}
]
}
]
}
segments[].words[]は、--word_timestamps trueの場合に単語単位のタイミングを返しますprobabilityは信頼度を示します(< 0.5 = 誤りの可能性が高い)
YouTube json3 字幕の解析
フォーマット構造
{
"events": [
{
"tStartMs": 1230,
"dDurationMs": 5000,
"segs": [
{"utf8": "hello ", "tOffsetMs": 0},
{"utf8": "world ", "tOffsetMs": 200},
{"utf8": "how ", "tOffsetMs": 450},
{"utf8": "are you", "tOffsetMs": 700}
]
}
]
}
単語のタイミングの抽出
各イベントと、そのイベント内の各セグメントについて:
word_start_ms = event.tStartMs + seg.tOffsetMsword_start_secs = word_start_ms / 1000.0word_text = seg.utf8.trim()
segs のないイベントは改行または書式設定なので、スキップします。
"\n" のみを含む segs を持つイベントは改行なので、スキップします。
文字起こしからの SRT 生成
SRT フォーマット
1
00:00:00,000 --> 00:00:02,500
First line of caption text
2
00:00:02,500 --> 00:00:05,100
Second line of caption text
適切な SRT を作成するルール
- 単語を 8~12 語ほどの字幕行にまとめます(1 行あたり 2~3 秒)
- 自然な間(ピリオド、カンマ、節の区切り)で改行します
- モバイルで読みやすいよう、各行を 42 文字未満にします
- クリップ開始時刻を基準にタイムスタンプを調整します(すべてのタイムスタンプからクリップ開始時刻を引きます)
- タイムスタンプ形式:
HH:MM:SS,mmm(ピリオドではなくカンマで区切る) - 各エントリー:インデックス行、タイムスタンプ行、テキスト行、空行
- SRT ファイルの作成には
file_writeツールを使用してください — すべてのプラットフォームで同じように動作します
ASS フォーマットによるスタイル付き字幕
アニメーション付き/スタイル付き字幕には、SRT の代わりに ASS 字幕フォーマットを使用します:
ffmpeg -i clip.mp4 -vf "subtitles=clip.ass:force_style='FontSize=22,FontName=Arial,Bold=1,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=2,Shadow=1,Alignment=2,MarginV=40'" -c:a copy output.mp4
主な ASS スタイルプロパティ:
PrimaryColour=&H00FFFFFF— 白いテキスト(AABBGGRR 形式)OutlineColour=&H00000000— 黒い縁取りOutline=2— 縁取りの太さAlignment=2— 下部中央MarginV=40— 下端からの余白FontSize=22— 1080x1920 の縦長動画に適したサイズ
FFmpeg による動画処理
シーン検出
ffmpeg -i input.mp4 -filter:v "select='gt(scene,0.3)',showinfo" -f null - 2>&1
- 閾値 0.1 = 非常に高感度、0.5 = 大きなカットのみ
- showinfo の出力から
pts_time:を解析してタイムスタンプを取得します - macOS/Linux では
grep showinfoにパイプし、Windows ではfindstr showinfoにパイプします
無音検出
ffmpeg -i input.mp4 -af "silencedetect=noise=-30dB:d=1.5" -f null - 2>&1
d=1.5= 最低1.5秒間の無音- 出力内の
silence_startとsilence_endを確認します
クリップの抽出
# Re-encoded (accurate cuts)
ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -c:v libx264 -c:a aac -preset fast -crf 23 -movflags +faststart -y clip.mp4
# Lossless copy (fast but may have keyframe alignment issues)
ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -c copy -y clip.mp4
-ssを-iより前に指定 = 高速シーク(抽出におすすめ)-to= 終了タイムスタンプ、-t= 長さ
縦型動画(Shorts/Reels/TikTok向けの9:16)
# Center crop (when source is 16:9)
ffmpeg -i input.mp4 -vf "crop=ih*9/16:ih:(iw-ih*9/16)/2:0,scale=1080:1920" -c:a copy output.mp4
# Scale with letterbox padding (preserves full frame)
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black" -c:a copy output.mp4
字幕の焼き込み
# SRT subtitles with styling (use relative path or forward-slash absolute path)
ffmpeg -i input.mp4 -vf "subtitles=subs.srt:force_style='FontSize=22,FontName=Arial,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=2,Alignment=2,MarginV=40'" -c:a copy output.mp4
# Simple text overlay
ffmpeg -i input.mp4 -vf "drawtext=text='Caption':fontsize=48:fontcolor=white:borderw=3:bordercolor=black:x=(w-text_w)/2:y=h-th-40" output.mp4
Windowsのパスのエスケープ:subtitles=C\\:/Users/me/subs.srt(コロンの前にバックスラッシュを2つ付けます)
サムネイルの生成
# At specific time (2 seconds in)
ffmpeg -i input.mp4 -ss 2 -frames:v 1 -q:v 2 -y thumb.jpg
# Best keyframe
ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)',scale=1280:720" -frames:v 1 thumb.jpg
# Contact sheet
ffmpeg -i input.mp4 -vf "fps=1/10,scale=320:-1,tile=4x4" contact.jpg
動画の分析
# Full metadata (JSON)
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
# Duration only
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4
# Resolution
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 input.mp4
APIベースのSTTリファレンス
Groq Whisper API
最速のクラウドSTTです。Groqのハードウェア上でwhisper-large-v3を使用します。無料枠を利用できます。
curl -s -X POST "https://api.groq.com/openai/v1/audio/transcriptions" \
-H "Authorization: Bearer $GROQ_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "[email protected]" \
-F "model=whisper-large-v3" \
-F "response_format=verbose_json" \
-F "timestamp_granularities[]=word" \
-o transcript_raw.json
レスポンス:{"text": "...", "words": [{"word": "hello", "start": 0.0, "end": 0.32}]}
- 最大ファイルサイズ:25MB。これより長い音声は、まずffmpegで分割します。
- 単語単位のタイミングを取得するには、
timestamp_granularities[]=wordが必要です。
OpenAI Whisper API
curl -s -X POST "https://api.openai.com/v1/audio/transcriptions" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "[email protected]" \
-F "model=whisper-1" \
-F "response_format=verbose_json" \
-F "timestamp_granularities[]=word" \
-o transcript_raw.json
レスポンス形式はGroqと同じです。最大25MBです。
Deepgram Nova-2
curl -s -X POST "https://api.deepgram.com/v1/listen?model=nova-2&smart_format=true&utterances=true&punctuate=true" \
-H "Authorization: Token $DEEPGRAM_API_KEY" \
-H "Content-Type: audio/wav" \
--data-binary @audio.wav \
-o transcript_raw.json
レスポンス:{"results": {"channels": [{"alternatives": [{"words": [{"word": "hello", "start": 0.0, "end": 0.32, "confidence": 0.99}]}]}]}}
- ストリーミングに対応していますが、クリップにはバッチモードを使用します。
smart_format=trueを指定すると、句読点と大文字・小文字が追加されます。
TTSリファレンス
Edge TTS(無料、APIキー不要)
# List available voices
edge-tts --list-voices
# Generate speech
edge-tts --text "Your caption text here" --voice en-US-AriaNeural --write-media tts_output.mp3
# Other good voices: en-US-GuyNeural, en-GB-SoniaNeural, en-AU-NatashaNeural
インストール:pip install edge-tts
OpenAI TTS
curl -s -X POST "https://api.openai.com/v1/audio/speech" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"tts-1","input":"Your text here","voice":"alloy"}' \
--output tts_output.mp3
音声:alloy、echo、fable、onyx、nova、shimmer
モデル:tts-1(高速)、tts-1-hd(高品質)
ElevenLabs
curl -s -X POST "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM" \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Your text here","model_id":"eleven_monolingual_v1"}' \
--output tts_output.mp3
Voice ID 21m00Tcm4TlvDq8ikWAM = Rachel(デフォルト)。音声の一覧:GET /v1/voices
音声の結合(TTS+オリジナル音声)
# Mix TTS over original audio (original at 30% volume, TTS at 100%)
ffmpeg -i clip.mp4 -i tts.mp3 \
-filter_complex "[0:a]volume=0.3[orig];[1:a]volume=1.0[tts];[orig][tts]amix=inputs=2:duration=first[out]" \
-map 0:v -map "[out]" -c:v copy -c:a aac -y clip_voiced.mp4
# Replace audio entirely (no original audio)
ffmpeg -i clip.mp4 -i tts.mp3 -map 0:v -map 1:a -c:v copy -c:a aac -shortest -y clip_voiced.mp4
品質とパフォーマンスのヒント
- クイックプレビューには
-preset ultrafast、最終出力には-preset slowを使用します - 高品質にするには
-crf 23を使用します(18=高品質、28=低品質、数値が小さいほどファイルサイズが大きくなります) - Webに適したMP4にするには
-movflags +faststartを追加します - CPUコア数を自動検出するには
-threads 0を使用します - 確認なしで上書きするには、必ず
-yを使用します
Telegram Bot APIリファレンス
sendVideo — チャット/チャンネルに動画をアップロードして送信
curl -s -X POST "https://api.telegram.org/bot<BOT_TOKEN>/sendVideo" \
-F "chat_id=<CHAT_ID>" \
-F "video=@clip_N_final.mp4" \
-F "caption=Clip title here" \
-F "parse_mode=HTML" \
-F "supports_streaming=true"
パラメーター
| パラメーター | 必須 | 説明 |
|---|---|---|
chat_id | はい | チャンネル(-100XXXXXXXXXX または @channelname)、グループ、またはユーザーの数値ID |
video | はい | アップロードする場合は @filepath(最大50MB)、再送信する場合はTelegramの file_id |
caption | いいえ | テキストキャプション。最大1024文字 |
parse_mode | いいえ | 書式付きキャプションには HTML または MarkdownV2 |
supports_streaming | いいえ | true にするとプログレッシブ再生が有効になります |
成功レスポンス
{"ok": true, "result": {"message_id": 1234, "video": {"file_id": "BAACAgI...", "file_size": 5242880}}}
エラーレスポンス
{"ok": false, "error_code": 400, "description": "Bad Request: chat not found"}
よくあるエラー
| エラーコード | 説明 | 対処方法 |
|---|---|---|
| 400 | チャットが見つかりません | chat_idを確認します。ボットをチャンネル/グループに追加する必要があります |
| 401 | 認証されていません | ボットトークンが無効か、取り消されています。@BotFatherから再生成します |
| 413 | リクエストエンティティが大きすぎます | ファイルが50MBを超えています。再エンコードします:ffmpeg -i input.mp4 -fs 49M -c:v libx264 -crf 28 -preset fast -c:a aac -y output.mp4 |
| 429 | リクエストが多すぎます | レート制限中です。レスポンスに記載された retry_after の秒数だけ待ちます |
ファイルサイズの上限
Telegram Bot APIでアップロードできる動画のサイズは最大 50MB です。クリップがこれを超える場合:
ffmpeg -i clip_N_final.mp4 -fs 49M -c:v libx264 -crf 28 -preset fast -c:a aac -movflags +faststart -y clip_N_tg.mp4
WhatsApp Business Cloud APIリファレンス
2段階のフロー:メディアをアップロード → メッセージを送信
WhatsApp Cloud APIでは、まず動画をアップロードして media_id を取得し、そのIDを参照するメッセージを送信する必要があります。
ステップ1 — メディアをアップロード
curl -s -X POST "https://graph.facebook.com/v21.0/<PHONE_NUMBER_ID>/media" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-F "file=@clip_N_final.mp4" \
-F "type=video/mp4" \
-F "messaging_product=whatsapp"
成功レスポンス:
{"id": "1234567890"}
ステップ2 — 動画メッセージを送信
curl -s -X POST "https://graph.facebook.com/v21.0/<PHONE_NUMBER_ID>/messages" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "<RECIPIENT_PHONE>",
"type": "video",
"video": {
"id": "<MEDIA_ID>",
"caption": "Clip title here"
}
}'
成功レスポンス:
{"messaging_product": "whatsapp", "contacts": [{"wa_id": "14155551234"}], "messages": [{"id": "wamid.HBgL..."}]}
ファイルサイズの上限
WhatsAppでアップロードできる動画のサイズは最大 16MB です。クリップがこれを超える場合:
ffmpeg -i clip_N_final.mp4 -fs 15M -c:v libx264 -crf 30 -preset fast -c:a aac -movflags +faststart -y clip_N_wa.mp4
24時間のメッセージ送信ウィンドウ
WhatsAppでは、(テンプレートを使用しないメッセージの場合)過去24時間以内に受信者からメッセージを受け取っている必要があります。「template required」エラーが発生した場合は、次のいずれかを行います。
- まず受信者からビジネス番号に何らかのメッセージを送ってもらいます
- 自由形式の動画メッセージの代わりに、事前承認済みのメッセージテンプレートを使用します
よくあるエラー
| エラーコード | 説明 | 対処方法 |
|---|---|---|
| 100 | パラメーターが無効です | phone_number_id と受信者の形式を確認してください(+ 接頭辞やスペースは使用できません) |
| 190 | アクセストークンが無効または期限切れです | Meta Business Settings でトークンを再生成してください。一時トークンの有効期限は24時間です |
| 131030 | 受信者が許可リストに登録されていません | テストモードでは、Meta Developer Portal で受信者を許可された番号に追加してください |
| 131047 | 再エンゲージメントメッセージまたはテンプレートが必要です | 受信者から24時間以内にメッセージが届いていません。テンプレートを使用するか、先にメッセージを送るよう依頼してください |
| 131053 | メディアのアップロードに失敗しました | ファイルが大きすぎるか、対応していない形式です。16MB未満の MP4 に再エンコードしてください |