活用シーンとソリューション

商品紹介ショート動画を自動作成:写真・AI ナレーション・字幕から ffmpeg で 9:16 縦型動画を生成

6 ステップ 11 分で読めます 56 回閲覧 0
目次

TikTok Shop、Shopee Video、Instagram Reels、YouTube ショートでは商品紹介のショート動画が売上につながりますが、商品ごとに手作業で動画を編集していては、カタログ全体には対応しきれません。この記事では、サーバー上の小さな Python スクリプトと ffmpeg を使い、商品写真と短いナレーション台本を入れたフォルダーから、AI ナレーション、焼き込み字幕、任意の BGM 付きの 9:16 縦型動画を完成させます。さらに、数百商品分の動画を一括で生成します。

写真、音楽、フォントは、使用する権利のあるものだけを使ってください。AI で生成した音声は、各プラットフォームのルールに従って表示してください。TikTok や YouTube などでは、リアルな合成コンテンツであることの開示が求められています。

ステップ1:サーバーを準備

この記事は Kokoro による AI ナレーションの内容を前提としています。先にその記事の手順で /opt/tts と tts.py を用意してください。続いて、中国語・日本語字幕用のフォントをインストールします。

apt install -y ffmpeg fonts-noto-cjk
fc-list | grep -i "Noto Sans CJK" | head -3

ステップ2:商品ごとにフォルダーを用意

/data/videos/LS-01/
├── 01.jpg          # photos, shown in name order
├── 02.jpg
├── 03.jpg
├── script.txt      # narration, one subtitle line per line
└── music.mp3       # optional background music
  • 写真は 3~6 枚使います。白背景のすっきりした画像が適しています。商品写真の背景を一括で削除する方法も参照してください。
  • 台本は 3~8 行の短い文にし、1 行あたり中国語なら約 15 文字、ラテン文字なら約 40 文字に収めると、どの字幕も 1~2 行で表示できます。
  • 台本に使う商品情報は AI で下書きすることもできます(AI で商品説明文を一括作成する方法を参照)。ただし、音声を作成する前に必ず内容を確認してください。

ステップ3:動画作成スクリプトを作成

cat > /opt/tts/makevideo.py <<'EOF2'
import os, subprocess, sys
import soundfile as sf

W, H, FPS = 1080, 1920, 30
FONT = os.environ.get("SUB_FONT", "Noto Sans CJK SC")
os.chdir(sys.argv[1])
images = sorted(f for f in os.listdir(".") if f.lower().endswith((".jpg", ".jpeg", ".png", ".webp")))
if not images:
    sys.exit("No photos found in " + os.getcwd())
per = sf.info("script.wav").duration / len(images)       # each photo stays on screen for an equal share

def ffmpeg(*args):
    subprocess.run(["ffmpeg", "-y", "-loglevel", "error", *args], check=True)

with open("clips.txt", "w") as lst:
    for i, img in enumerate(images):
        clip = f"clip{i:03d}.mp4"                           # photo centred on a blurred copy of itself, 9:16
        ffmpeg("-loop", "1", "-t", f"{per:.3f}", "-i", img, "-filter_complex",
               f"[0:v]split[a][b];[a]scale={W}:{H}:force_original_aspect_ratio=increase,crop={W}:{H},boxblur=20[bg];"
               f"[b]scale={W}:{H}:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2,format=yuv420p",
               "-r", str(FPS), "-c:v", "libx264", "-preset", "veryfast", "-crf", "20", clip)
        lst.write(f"file '{clip}'\n")

style = f"FontName={FONT},FontSize=11,Bold=1,Outline=2,Shadow=0,Alignment=2,MarginV=50"
inputs = ["-f", "concat", "-safe", "0", "-i", "clips.txt", "-i", "script.wav"]
if os.path.exists("music.mp3"):                             # optional background music, quietly under the voice
    inputs += ["-stream_loop", "-1", "-i", "music.mp3"]
    audio = "[2:a]volume=0.15[m];[1:a][m]amix=inputs=2:duration=first,loudnorm=I=-14:TP=-1.5[a]"
else:
    audio = "[1:a]loudnorm=I=-14:TP=-1.5[a]"
ffmpeg(*inputs, "-filter_complex", f"[0:v]subtitles=script.srt:force_style='{style}'[v];{audio}",
       "-map", "[v]", "-map", "[a]", "-c:v", "libx264", "-preset", "veryfast", "-crf", "20",
       "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "160k", "-ar", "48000", "-ac", "2", "-shortest", "-movflags", "+faststart", "video.mp4")
for f in ["clips.txt"] + [f"clip{i:03d}.mp4" for i in range(len(images))]:
    os.remove(f)
print("done:", os.path.abspath("video.mp4"))
EOF2

各写真は、ナレーションの長さを写真の枚数で均等に割った時間だけ表示されます。写真は、その写真自体をぼかして全画面に広げた背景の中央に配置されるため、横長の写真も縦長の写真も縦型の画面いっぱいに表示されます。その後、スクリプトはクリップをつなぎ合わせ、音声と、BGM がある場合は小さめの音量の BGM を加え、字幕を焼き込み、ラウドネスを約 -14 LUFS に正規化して video.mp4 を書き出します。

ステップ4:最初の動画を作成

cd /data/videos/LS-01
TTS_LANG=z TTS_VOICE=zf_xiaobei /opt/tts/bin/python /opt/tts/tts.py script.txt
/opt/tts/bin/python /opt/tts/makevideo.py /data/videos/LS-01

出力は 1080x1920、30 fps の H.264 動画(音声は AAC)で、主要なショート動画プラットフォームすべてが受け付ける形式です。字幕は画面の下端から少し上に配置され、ほとんどのプラットフォームでボタンと重なりません。日本語字幕の場合は、2 つ目のコマンドを SUB_FONT="Noto Sans CJK JP" を付けて実行します。字幕のサイズや位置を変えるには、スクリプトの style 行にある FontSize と MarginV を調整してください。

ステップ5:カタログ全体の動画を作成

for d in /data/videos/*/; do
  [ -f "$d/video.mp4" ] && continue                    # skip products that are already done
  TTS_LANG=z TTS_VOICE=zf_xiaobei /opt/tts/bin/python /opt/tts/tts.py "$d/script.txt" &&
  /opt/tts/bin/python /opt/tts/makevideo.py "$d" || echo "FAILED: $d"
done

時間のかかるバッチ処理は、nohup を付けるか screen の中で実行すると、ログアウトした後も処理が続きます。当社のテストでは、16 秒の動画のレンダリングに約 5 秒かかりました。処理時間の大半は動画のエンコードなので、マルチコア CPU が効果的です。

ステップ6:公開前に確認

  1. すべての動画を一度は視聴してください。読み間違い、字幕の誤字、写真の切り抜きの不具合はすぐに見つかります。
  2. BGM が声をかき消していないか確認します。必要に応じて、スクリプトの volume=0.15 の値を下げてください。
  3. アップロード前に、動画の長さ、キャプション、AI コンテンツのラベルについて、各プラットフォームの最新の要件を確認してください。

よくある質問

写真の代わりに短い動画クリップを使えますか?

使えます。ただし、クリップも同じように長さを切りそろえてスケーリングする必要があるため、スクリプトの改修が必要です。より簡単なのは、ナレーションの記事の手順で音声と SRT を作成し、動画編集ソフトで手持ちのクリップと組み合わせる方法です。

同じ動画を他の言語でも作るには?

script.txt を翻訳し、その言語のボイスを指定して 2 つのコマンドを実行します。既存の動画については、AI による動画の多言語吹き替えを参照してください。

中国語の字幕が四角い枠で表示される

フォントがインストールされていません。ステップ1のとおり fonts-noto-cjk をインストールし、fc-list に「Noto Sans CJK SC」が表示されることを確認してください。

上記の手順で解決しない場合は、サポートチケットを送信して IMIDC の 24 時間 365 日対応テクニカルサポートへご連絡ください。サーバー IP、OS バージョン、フォルダー構成、エラー全文を添えていただくと、より迅速に調査できます。

この回答はお役に立ちましたか?

関連チュートリアル