ブログ記事と画像からショート動画を自動生成する仕組みを作り始め、ようやく**「動画として組み立てる工程」**まで進みました。
これまでは、記事をAIで解析し、動画テーマを抽出してScene Planを作成。AIナレーションを生成し、実際の音声尺に合わせてSceneを調整するところまで作ってきました。
ただし、ここまでで完成するのは動画の材料と設計図です。
今回はそこからさらに進めて、Pythonだけで画像・字幕・UI・モーション・ナレーション・BGMを合成し、縦型MP4として出力する仕組みを実装しました。
途中では効果音(SFX)も試しましたが、最終的には外しています。実際に作ってみると、機能を追加するだけでなく、不要なものを削ることも自動化では重要だと分かりました。
この記事で分かること
- Pythonでショート動画を組み立てる基本構造
- Sceneとテンプレートを使う理由
- 字幕・UI・モーションを自動配置する考え方
- BGMを自動合成する方法
- SFXを実装したものの外した理由
- 動画を「編集」ではなく「ルール」で作る考え方
動画サイズは1080×1920pxに固定
まず動画のキャンバスを1080×1920px(9:16)に固定しました。
YouTubeでは現在、3分以内で正方形または縦長の動画をパソコンからShortsとしてアップロードできます。(Google ヘルプ)
今回1080×1920pxにしたのは、YouTube Shortsだけでなく、縦型ショート動画として他媒体にも展開しやすくするためです。
サイズを固定すると、Python側でもタイトル、字幕、画像、UIなどの表示位置を毎回考える必要がありません。
動画の外枠を固定し、中身だけ記事ごとに入れ替える設計にできます。
動画をScene単位で組み立てる
1本の動画をまとめて作るのではなく、複数のSceneに分けてレンダリングします。
例えば、
フック → 基本説明 → 具体例 → 重要ポイント → まとめ
という構成です。
AIが作成したScene Plan JSONには、Sceneの種類、見出し、ナレーション、使用画像、アクセントカラーなどを記録します。
Pythonはこれを読み込み、Sceneを一つずつ生成して最後に連結します。
この構造なら、「タイトルSceneだけ変更する」「比較Sceneのレイアウトを修正する」といった改善も可能です。
Sceneごとにテンプレートを用意する
Sceneには、TITLE・POINT・EXAMPLE・COMPARISON・SUMMARYなどの種類を持たせます。
ここでも、
AI=何を伝えるかを判断する
Python=どう表示するかを実行する
という役割分担を使います。
AIは「ここはPOINT Scene」と判断しますが、文字位置や画像サイズまで自由に決めません。
POINTならタイトルはここ、画像はこの範囲、アクセントラインはこの位置、とPython側のテンプレートで固定します。
これによって記事が変わっても、動画全体の統一感を保ちやすくなります。
字幕もPythonで自動配置する
ナレーション全文をそのまま字幕にすると、スマートフォンでは文字だらけになります。
そこで文章を、
「CPAとは?」
「成果1件を獲得するために」
「使った広告費」
といった短い単位へ分け、画面上で読みやすい量にします。
字幕位置や文字サイズについても、毎回AIに判断させるのではなくPython側で基本ルールを固定します。
SNSでは画面上に操作UIが重なるため、重要な情報を端へ配置しないよう安全な表示領域もあらかじめ決めておきます。
静止画に軽いモーションを加える
画像と字幕だけでも動画ファイルは作れますが、実際に見ると音声付きスライドに近い印象でした。
そこで、画像の緩やかなズーム、わずかな移動、文字のフェードイン、アクセントラインの表示など、軽いモーションを追加しました。
ただし、モーションもAIに自由生成させません。
POINTなら軽いズーム、COMPARISONなら左右から表示する、といったようにSceneタイプと動きを紐付けます。
派手さよりも、何本生成してもレイアウトが崩れないことを優先しています。
UIでシリーズとしての統一感を作る
Scene番号、進行バー、情報カード、アクセントラインなどのUIも追加しました。
ここでは、記事画像から取得したアクセントカラーを利用します。
基本的なデザインは共通にしながら、青の記事なら青、赤なら赤と強調色を変えることで、シリーズとしての統一感と記事ごとの違いを両立する狙いです。
ただしUIも増やしすぎれば情報の邪魔になります。実際の動画を確認しながら、理解を助けるものだけを残します。
BGM「Cyan Forward」も自動合成
映像とナレーションに加えて、BGMもPythonから合成するようにしました。
現在は「Cyan Forward」を基本BGMとして使い、完成動画の長さに合わせて調整します。
動画が31.8秒ならBGMも31.8秒まで使用し、ナレーションを邪魔しない音量へ下げます。
BGMが動画全体を通して流れることで、Sceneが切り替わっても一本の動画としてつながって見えるようになりました。
なお、BGMを継続利用する場合は利用許諾の確認が必要です。YouTubeも、外部で作成したShortsでは使用する著作物の権利を確認するよう案内しています。YouTubeオーディオライブラリには、YouTube上で著作権上安全に利用できる音楽や効果音も用意されています。(Google ヘルプ)
SFXを実装したものの、最終的に外した
BGMの次に、Scene切り替えや重要情報の表示時に「シュッ」「ポン」といったSFX(効果音)も試しました。
技術的にはPythonから問題なく組み込めます。
しかし完成動画を見ると、ナレーション、字幕、画像、UI、モーション、BGMにさらに効果音が加わり、少し情報量が多いと感じました。
今回作りたいのはエンタメ中心ではなく、短時間で知識を伝える動画です。
そのためSFXは実装したものの、現在のテンプレートからは外しました。
「実装できる」と「入れた方がよい」は別の話だと分かった検証でもあります。
Python化すると「動画」ではなく「ルール」を修正できる
Pythonで動画を作る最大の目的は、高度な編集ソフトを置き換えることではありません。
価値を感じているのは、同じ制作ルールを何度でも実行できることです。
現在は、
1080×1920 → Sceneテンプレート → 字幕 → UI → 軽いモーション → AIナレーション → BGM → SFXなし → MP4
という基本形になりました。
例えば50本作った後に字幕を大きくしたくなっても、50本を手作業で編集するのではなく、Python側の設定を変更して再レンダリングできます。
つまり、完成動画を直すのではなく、動画を作るルールそのものを改善するという考え方です。
まとめ
今回、Pythonだけで字幕・UI・モーション・ナレーション・BGMを組み合わせ、1080×1920pxのショート動画として書き出すところまで進みました。
実装してみて分かったのは、動画生成システムでは機能を増やすこと以上に、何を固定し、何を変化させるかを決めることが重要だということです。
SFXのように一度追加してから外した機能もあります。それも実際の動画を確認したからこそできた改善です。
目指しているのは、Pythonで凝った動画を1本作ることではありません。
記事と画像を入力すれば、一定のルールと品質で何度でもショート動画を生成できる仕組みを作ること。
今後も完成動画を見ながら生成ルールを修正し、少しずつ「動画制作エンジン」として育てていきます。

