ナレーション + 字幕付きショートビデオ生成
パイプライン: スクリプト .txt → make_video.py (edge-tts で各文を読み上げ → 音声結合 → 実時間に合わせたASS字幕 → 背景合成 + ffmpegで字幕焼き付け) → MP4 1080x1920
確定モード: 既存音声 → ビデオ(ユーザーがmp3を送信した場合のデフォルト)
ユーザーがEverAI上で音声を作成(Web、速度0.85)、mp3 + 台詞を送信します。API呼び出しや声のクローン、機械上での音声モデル(VieNeu)実行は行いません。
- 台詞を
.txtファイルに分割(各文はコンマ/ピリオド/「...」で区切った短い塊、#行や[icon]は除去)。 python3 make_video.py kichban.txt ~/Downloads/<名前>.mp4 --audio voice.mp3 --style night --no-wave --bg assets/pho-dem.mp4 --target <長さ±5>- 各行のタイミングを出力: 上記コマンドに
--print-timingを追加(レンダリングなし)。確認: 文字数に対して異常に長い/短い行がある場合は結合/分割して再レンダリング。 - 字幕を確認するために1〜2フレームを抽出、パスと長さを報告。音が聞こえない場合は、通常MacがAirPodsに出力しているためです。
ユーザー向けガイド:
HUONG-DAN.md
他のマシンへのインストール
フォルダ ~/.claude/skills/short-video/ を新しいマシンにコピー(同じパス)、次に bash ~/.claude/skills/short-video/setup.sh を実行。macOSおよびUbuntu/Debianに対応。Windowsの場合はWSL経由で使用。夜の街の背景動画は付属: assets/pho-dem.mp4(Mixkitのストック素材、商用利用可)。
要件(このマシンにはインストール済み)
ffmpeg-full(subtitles/libassフィルタが必要):brew install ffmpeg-fulledge-tts:pipx install edge-tts(ネットワークエラー時は自動でsay -v Linhにフォールバック)
ステップ 1 — ブリーフィングの確定
リクエストから取得。不足している場合はデフォルト値を使用し、トピックがまったく不明な場合のみ質問:
- トピック / 視点 — 具体的な視点がない場合は、魅力的で具体的なものを自動選択。
- 長さ — デフォルト45〜60秒。
- 音声 — デフォルト女性
vi-VN-HoaiMyNeural; 男性vi-VN-NamMinhNeural。その他の言語:edge-tts --list-voices | grep <コード>(例en-US-AriaNeural)。 - 背景 / 音楽 — ユーザーから提供された画像/動画、なければデフォルトのグラデーション背景。
ステップ 2 — スクリプト作成
.txtファイルとして保存。最初の行はタイトル、以降は各文を1行:
# 画面上部に表示される短いタイトル(6単語以内)
好奇心をそそるフック文、12単語以内。
内容文...
結論 + 行動喚起。
ルール:
- ベトナム語の長さ: 約2.3単語/秒(実測: 155単語 ≈ 65秒)。45〜60秒 → 110〜140単語; 30秒 → 約65単語; 15秒 → 約30単語。
- 各行は1文、8〜20単語。最初の3秒はフック(質問 / 驚くべき事実)。中盤: 3〜5の具体的で覚えやすいポイント。最後: CTA(保存、フォロー、コメント)。
- 事実は正確であること。健康/金融/法律のトピック: 診断や専門家のような具体的なアドバイスはしない。必要に応じて専門家に相談するよう促す。
- 数字/記号は読み間違えやすい場合は漢字で書く(「4-7-8」の代わりに「四・七・八」、「%」の代わりに「パーセント」)。絵文字や
{}\は避ける。
ユーザーが既に内容を提供しているか「そのまま進めて」と言った場合を除き、レンダリング前にスクリプトを確認させる。
ステップ 3 — レンダリング
python3 ~/.claude/skills/short-video/make_video.py kichban.txt out.mp4 \
[--voice vi-VN-HoaiMyNeural] [--rate -5%] [--target 45-60] \
[--bg background_image_or_video] [--music bgm.mp3] [--gap 0.35] \
[--pitch -8Hz] [--style default|night]
- 既存音声:
--audio voice.mp3でTTSをスキップ。スクリプトは読み上げと一致し、各行が短い塊(コンマ/ピリオドで区切る)であること。文のタイミングは休止箇所に合わせる。--print-timingでタイミングを出力(通常約12〜16文字/秒)、異常に長い/短い行は結合/分割して再レンダリング。 - FPT.AI:
--engine fpt --voice leminh(北部男性; 他にbanmai,thuminh北部女性,lannhi,linhsan南部女性,myan中部女性,giahuy中部男性)。export FPT_API_KEY=...が必要(キーは console.fpt.ai、Free Tier月10万文字)。各文字のタイムスタンプがないため、カラオケは文字数で分割。--rateはatempoで適用。キーをスキルファイルに記録しないこと。 - すべてのエンジンは人間らしいリズムで読み上げ(各文で速度/ピッチが微妙に変動、疑問文の後は長めの間)+温かみのある声処理、コンプレッション、軽いリバーブ。話し言葉に合わせてスクリプトを作成し、「...」や文中のピリオドで息継ぎ位置を作る。
- 低く大人っぽい北部男性声(edge):
--voice vi-VN-NamMinhNeural --pitch=-8Hz --rate=-10%(NamMinhは唯一の男性ベトナム語edge音声)。 --style night --no-wave+ スクリプトに#行や[icon]タグがない → 背景+字幕のみ。--style night(「夜の街」リールスタイル): タイトルは大文字で文字間隔を広げ、teal色+下線、細線ネオンアイコン、カラオケ字幕は大文字で一文字ずつ(edge-ttsの実タイムスタンプ使用)、波形は線状。文頭に[icon]を置くとその文からアイコン変更:sun hourglass gift heart leaf book star eye。背景は実際の夜の街動画がおすすめ: Mixkitで無料ストック(https://mixkit.co/free-stock-video/night-city-street/、リンクassets.mixkit.co/videos/<id>/<id>-1080.mp4)、複数クリップを結合、縦にクロップ、setpts=1.4*PTSでスロー。--style ui(テクノロジー解説ビデオ): ダークグリッド背景、シリーズタイトルバー(#)+ステップボックス1..n、シミュレートされたアプリウィンドウ、キーボード入力するターミナル、*キーワード*をオレンジでハイライトする字幕枠。文頭タグ:[step:ステップ名](新しいステップへ)、[card:タイトル|項目1|項目2](ウィンドウ、次のシーンまで保持)、[term:コマンド]。ショートカットキーの読み上げは文字で書く(「コマンド、シフト、スリー」)、カード内では「Command + Shift + 3」と表記。サンプル: 音声vi-VN-NamMinhNeural --pitch=-4Hz --rate=+15% --gap 0.25。--bgなし → 青紫の暗めグラデーション背景がゆっくり動く(落ち着いたトピックに合う; 活発なトピックには背景画像/動画を提供してもらう)。画像 → スローズーム効果。動画 → 自動ループ。--musicは音量12%に下げられ、最後にフェードアウト。- スクリプトが長さを出力し、
--targetの範囲外の場合は警告 → 文を追加/削除するか--rateを調整して再レンダリング。
ステップ 4 — 確認
1フレーム抽出して字幕の文字化けやはみ出しをチェック:
ffmpeg -v error -y -ss 5 -i out.mp4 -frames:v 1 frame.jpg その後 frame.jpg を読み取る。ユーザーにビデオの絶対パスと長さを報告。
サンプルスクリプト: example-sleep.txt(スキルフォルダ内)