ffmpeg 自動編集・動画アセンブル · Auto-assemble with ffmpeg
storyboard.json → ナレーション(edge-tts)→ 各シーンに Ken Burns / 動画トリミング → xfade トランジション → ASS 字幕・テロップ → BGM ダッキングミックス → 2パス loudnorm(-14 LUFS)→ out/video.mp4 + .srt。
ecommerce-video-skills の一部 · スクリプトは全て
scripts/ディレクトリ内:assemble.py(メイン)·tts_edge.py·make_subs.py·make_bgm.py(ロイヤリティフリーなBGM合成)·make_cards.py(PILを使用した商品カード/エンドカード作成)
入力 Inputs
storyboard.json(selling-point-storyboardから生成可能)、素材のパスはこのファイルからの相対パス- 環境:Python 3.9+、
pip install pillow numpy edge-tts、ffmpeg(libass対応)、CJKフォント
クイックスタート Quick start
pip install pillow numpy edge-tts
python scripts/assemble.py examples/aura-bottle/storyboard.json -o out/aura.mp4 # リポジトリ付属のサンプル、約30秒でレンダリング完了
python scripts/assemble.py storyboard.json --tts none -o out/preview.mp4 # オフラインプレビュー(ナレーション無し、文字数で時間を推定)
python scripts/assemble.py storyboard.json --size 1080x1080 -o out/main-1x1.mp4 # メイン画像動画 1:1
python scripts/assemble.py storyboard.json --bgm music.mp3 # あなたの権利を持つ音楽を使用
storyboard フィールド Fields
| フィールド | 説明 |
|---|---|
トップレベル voice / rate / pitch | edge-tts の音色、話速(例:+10%)、ピッチ |
トップレベル bgm | "auto"(内蔵合成、ロイヤリティフリー)/ 音楽ファイルのパス / null |
トップレベル tag | 画面左上の常時表示ステッカー(ブランド名/型番/「デモ」など) |
image または video (+start) | 素材;動画の場合は start 秒から現在のシーン長だけ切り出し |
line | ナレーションテキスト;シーン長 = ナレーション長 + 0.15秒の先行 + pad |
sub | 字幕(デフォルトは line と同じ);"" でそのシーンの字幕を非表示;**強調**、` |
title / cta | テロップ / 行動喚起ボタン |
motion | zoom_in zoom_out pan_left pan_right pan_up pan_down punch static |
fit | auto(アスペクト比が近ければトリミング、そうでなければぼかし埋め)/ cover / blur |
transition | 次のシーンへの xfade 名:fade slideleft slideup smoothleft circleopen wipeleft … |
min / duration / pad | 最小長さ / 固定長さ / 文章後の余白(秒) |
手順 Steps
- 全素材が存在し、適切なサイズであることを確認(商品画像 ≥ 1000px);エンドカードが無ければ
make_cards.pyで生成:python scripts/make_cards.py --image main.png --name "商品名" --points "売り文句1|売り文句2|売り文句3" -o assets/end-card.png - まず
--tts noneで一度実行して画面のリズムを確認し、その後本番レンダリング。 - レンダリング後にフレームを抜き出して確認:
ffmpeg -ss 3 -i out/video.mp4 -frames:v 1 check.png platform-spec-exportに渡して各プラットフォーム版を書き出し;cover-title-abでサムネイルを作成。
パイプラインの詳細 How it works
- Ken Burns:フレームごとに
scale(eval=frame)+crop。zoompanよりもジッターが少ない;punch= 0.35秒の急速なズームイン(フック用)。 - トランジション:各シーンをトランジション長の半分だけ多くレンダリングし、xfade をシーン境界に配置。ナレーションの開始位置がトランジションで途切れることはありません。
- ミキシング:ナレーションはシーンの開始点に配置;BGM はデフォルト -20 dB、音声が存在する場合はさらに 10 dB 抑制(スムーズなダッキング);まずコンプレッサー/リミッターを適用し、その後2パスの loudnorm で約 -14 LUFS、TP -1.5 dB に調整。
- 字幕:実際のナレーション長を使って
build/timing.jsonを生成 →make_subs.py→ libass で書き込み、同時に.srtを出力。
チェックリスト Checklist
- 完成動画の長さ、解像度、フレームレートが正しいか(
ffprobe out/video.mp4) - 3フレーム抜き出して確認:字幕が商品にかかっていない、下部UIゾーンに入っていない
- 一度聴く:ナレーションが明瞭、BGMが邪魔しない、冒頭にノイズがない
- BGMに商用利用権限があるか(
autoで合成された音楽は安心して使用可能) - 素材(画像/動画/フォント)に使用権限があるか
よくある問題と修正 Failure fixes
| 問題 | 修正 |
|---|---|
ffmpeg failed | スクリプトが出力する stderr の末尾を確認;よくあるのはパスの誤りや ffmpeg が libass/libx264 をサポートしていないこと |
| 画面端がぼやける | 素材の解像度が低い;≥1080px の画像に変えるか、motion の強度を下げる(static に変更) |
| 商品が切り取られる | そのシーンで "fit": "blur" を設定 |
| トランジションで音声が途切れる | 発生しません(ナレーションはシーンの開始点に合わせています);カスタム duration が短すぎる場合は延長 |
| レンダリングが遅い | デフォルトで中間ファイルには veryfast を使用;最終エンコードの -preset medium を fast に変更可能 |
| 1:1 / 16:9 が必要 | --size 1080x1080 / --size 1920x1080、字幕サイズは自動で比率に合わせる |
参考と謝辞:着想は MoneyPrinterTurbo(MIT)の「スクリプト→ナレーション→字幕→合成」パイプラインに触発されましたが、本実装は独立した純 ffmpeg バージョンであり、そのコードを複製したものではありません。