縦型ショート動画をコマンド2つで作った。時間がかかったのは全部、日本語のほうだった

縦型ショート動画をコマンド2つで作った。時間がかかったのは全部、日本語のほうだった

#AI#動画#つくったもの#Python

縦型のショート動画を4本作りました。絵も声もありません。文字だけです。

作るのに使ったコマンドは、2つです。

VIDEO_TOPIC=akachan python3 slide_text.py    # 7枚のPNGを作る
python3 build_video.py --sec 3.6             # つないで mp4 にする

数秒で終わります。 詰まったのは、全部そのあとでした。

同じものを作る手順

用意するもの

pip install pillow imageio-ffmpeg

この2つだけです。 imageio-ffmpeg は、動画をつなぐ ffmpeg を同梱してくれます。

日本語フォントも要ります。Ubuntu / Debian ならこれで入ります。

sudo apt install fonts-ipafont-gothic

Windows なら C:/Windows/Fonts/meiryo.ttc、Mac なら /System/Library/Fonts/ヒラギノ角ゴシック W3.ttc を指定すれば動きます。

コピペで動く最小版

これを mini.py として保存して実行すると、7枚のPNGと mp4 が出ます。

import os, glob, subprocess
from PIL import Image, ImageDraw, ImageFont
import imageio_ffmpeg

FONT = "/usr/share/fonts/truetype/fonts-japanese-gothic.ttf"  # 環境に合わせて変える
W, H = 1080, 1920          # 縦型(9:16)
BG   = (40, 42, 50)        # 背景
INK  = (240, 240, 243)     # 文字
SEC  = 3.6                 # 1枚あたりの表示秒

SLIDES = [
    ("赤ちゃんは\n美人が好き", "らしい。1987年の実験"),
    ("実験",   "生後6か月の赤ちゃんに、\n顔写真を 2枚ずつ見せた。"),
    ("結果",   "美人のほうを 長く見た。\n7.24秒 と 6.59秒。"),
    ("0.65秒", "……差、これだけです。"),
    ("しかも", "3割の赤ちゃんは、\n逆を 長く見ていた。"),
    ("つまり", "「赤ちゃんは美人が好き」とは、\nまだ言えない。"),
]

os.makedirs("frames", exist_ok=True)
for i, (head, body) in enumerate(SLIDES):
    im = Image.new("RGB", (W, H), BG)
    d  = ImageDraw.Draw(im)
    d.multiline_text((W//2, H//2 - 160), head, font=ImageFont.truetype(FONT, 96),
                     fill=INK, anchor="mm", align="center", spacing=24)
    d.multiline_text((W//2, H//2 + 120), body, font=ImageFont.truetype(FONT, 52),
                     fill=INK, anchor="mm", align="center", spacing=20)
    im.save(f"frames/{i:02d}.png")

with open("frames/list.txt", "w") as f:                 # ffmpeg の concat 用リスト
    for p in sorted(glob.glob("frames/*.png")):
        f.write(f"file '{os.path.basename(p)}'\nduration {SEC}\n")
    f.write(f"file '{os.path.basename(p)}'\n")          # 最後の1枚はもう一度書く

subprocess.run([imageio_ffmpeg.get_ffmpeg_exe(), "-y", "-f", "concat",
                "-i", "frames/list.txt", "-vf", f"scale={W}:{H}",
                "-c:v", "libx264", "-pix_fmt", "yuv420p", "-r", "30", "out.mp4"])
python3 mini.py     # → out.mp4

ここまでで完成します。 あとは SLIDES の中身を書き換えるだけです。

つまずくとしたら3か所

フォントのパス ここが違うと cannot open resource で止まります。実在するパスを指定してください
concat の最後の1枚 リストの末尾で最後のフレームをもう一度書かないと、最後の1枚が一瞬で消えます(concat の仕様)
H.264 が使えない 環境の ffmpeg が軽量版だと libx264 がありません。imageio_ffmpeg.get_ffmpeg_exe() で同梱版を呼べば通ります

実際に使っているほうは

上のは説明用に削った版です。実際のスクリプトでは、これを足しています。

中身のほうで決めること5つ

ここからは、コードの話ではありません。1枚に何を書くかの話です。

技術で困ったのは、上の「ffmpegが軽量版だった」1件だけでした。残りの時間は全部、ここに使っています。

① 専門用語は、1枚まるごと使う覚悟がないなら入れない

論文の数字を扱うと、こういう表記がついてきます。

p < .001
相関 0.274
メタ分析
95%信頼区間

p < .001 は「偶然でこうなる確率は 0.1% 未満」という意味です。論文では、その結果が偶然かどうかを示すために必ず書きます。書いてあること自体は正しいです。

ただ、動画にこれを出すと、意味を説明するのに1枚まるごと必要になります。7枚しかないので、そこに1枚は使えません。

数字は残せます。消すのは、数字の呼び名のほうです。

✕  相関は0.274(p<.001)で有意
◎  0.274。「強い関係」の目安は0.3。ギリギリ届かない

② 文字は、画面の右端から離す

Shortsは画面の右側に、高評価・コメント・保存・共有のボタンが縦に並びます。そこに文字が隠れます。

SAFE_W = 780   # 文字を収める幅。画面は1080px

カードや背景まで細くしないでください。 文字も一緒に小さくなって、前より読みにくくなります。枠は広いまま、文字の折り返し幅だけ狭めます。

そして本当の直し方は、幅ではありません。文を短くするほうです。

③ 問いは、7枚で答えられる大きさにする

7枚で答えきれない問いを1枚目に置くと、最後まで見ても答えが出ません。

✕  疲れた日、なぜか食べてしまう。なぜ?        ← 原因が複数ある。1本に収まらない
◎  疲れた日に食べてしまうのは、ストレスのせい?  ← 「はい/いいえ」で閉じられる

大きい問いは、割るのではなく縮めます。 割ると、1本目が答えのないまま終わります。

④ 締めは、事実か解釈かを分ける

最後の1枚は、言いたくなることではなく、言えることだけにします。

✕  赤ちゃんが美を知ってるんじゃない。大人と少し重なっただけ
      → 「重なった」は解釈。実験が測ったのは秒数だけ

◎  「赤ちゃんは美人が好き」とは、まだ言えない
      → 証拠がどこまで届いているか、という事実

判定の仕方は1つです。 その文が、実験で測ったものだけで言えるか。言えないなら解釈です。

⑤ 中の5枚は、実験の説明に使わない

✕  16人 → 15分後 → 休息モード → でも → しかも

これは実験の手順です。 見ている人には、話がどこまで進んだのか分かりません。

5枚は、問いがどこまで進んだかに使います。「ふつうの答え → でも → 本当は → 数字 → ただし」の順です。

決まった型

7枚を、こう並べることにしました。

1  なぜ        実際に起きる場面 +「なぜ?」   ← 抽象語を使わない
2  ふつうの答え  みんなが思っている説明
3  でも        それが崩れる事実
4  本当は      原因
5  数字        ここで初めて根拠を出す
6  ただし      どこまで言えるか
7  つまり      1枚目の「なぜ」に、そのまま答える

1枚目と7枚目が対になります。根拠は真ん中に置きます。

そして5枚目が空でも、他の6枚は先に作れます。 実際、調べ物と並行して作っています。

まとめ

技術      コマンド2つ。数秒
決めること  5つ。全部、書いてある日本語の話

「AIで動画を作った」の中身は、ほとんど日本語の作業でした。

技術は再現できます。再現できないのは、1枚に何を書くかのほうです。

← 記事一覧へ