AIでミュージックビデオを作った話

あるラッパーの楽曲のミュージックビデオを作るにあたり、嬉しいことにAI作画を担当させてもらいました。

空に唄えば – NNC a.k.a. DJ KYOHEI
Moisture – NNC a.k.a. DJ KYOHEI

この背景で流れている映像を担当した。アーバンな曲調に合わせて煌びやかな街並みが流れ移りゆくようなものをイメージしていて、ミュージックビデオとはいっても今回は厳密にはリリックビデオ、あるいは最近でいうところのVisualizerなので、細かいところはあまり気にしていません。なのでよくよくみると細部(たとえば顔とかそれこそ手とか)はかなり描画が雑になっています。

中身は基本的に僕が前から推しているStable Diffusion Videos (nateraw/stable-diffusion-videos, 今後SDVと書く)です。

SDVは基本的には作成した2枚のイラストを使って、1枚目から2枚目への遷移を段階的に作成するライブラリ。つまり、ある(非常に短時間の)ワンシーンにおける映像の始まりと終わりの画像をプロンプトで指定することで2枚の画像が生成され、あとはその中間がザクザク作られていくイメージ。

つまり具体的な生成プロセスにおいては1回の映像出力に対して2つのプロンプトを突っ込まなければいけないんだけど、これが結構難しい。そもそもその2枚を思い通りに出力させるのが難しい上に、その遷移の最中に意外と全然違う方向にビジュアルが吹っ飛んだりもする。そこで(これはある種のテクニックとして)、今回の画像生成では一回の出力で使うプロンプトには2つとも同じものを指定して、シード値だけを変える形で作成した。

たとえば以下の2つは”many black shadows walking in the bright night city”的なプロンプト(厳密な表現は忘れた)を指定したもの。

これら2枚に対して中間層18枚(つまり始まりから終わりまで全部で20フレーム)込みで動画にすると以下のような感じ。

(今回はイメージを掴んでもらうことが目的なので動画はffmpegで軽くした上でアップしてます。)

SDVはColab上でGUI的な感じで走らせることができるけど、そんなことやってたら量を生成することは無理なので、内部のpipeline.walkのコードをひっぱってきてこちらでgenerate_videos的な感じで関数化していて、

def generate_videos(text, seed=10, fps=30, iter=20):
    h = 512; w = 768
    video_path = pipeline.walk(
        [text]*2,
        [seed, seed+1],
        fps=fps,                      # use 5 for testing, 25 or 30 for better quality
        num_interpolation_steps=iter, # use 3-5 for testing, 30 or more for better results
        height = h,                   # use multiples of 64 if > 512. Multiples of 8 if < 512.
        width  = w,                   # use multiples of 64 if > 512. Multiples of 8 if < 512.
        output_dir=outdir
    )
    print(video_path)
    visualize_video_colab(video_path)

ここではそもそも指定できるプロンプトは1つ、シードも一つ指定したら終わりはその1つ次の値になるようにしていて、あとはこれをループさせて

texts = [
    "many black shadows walking in the bright night city",
    "blah blah",
]
for t in texts:
    for s in range(10):
        generate_videos(text=t,seed=100+s, fps=30, iter=20)

みたいな感じで各プロンプトに対してとにかく大量に素材を作って、どれを使うかは後で考えるぐらいがちょうどいい。

ちなみにこのコードだと各プロンプトに対してseed100→101, 101→102, …, っていうふうに動画が作られていくわけだけど、前の動画とプロンプト、シードを全く同じにしておくというのがポイントになっていて、そうしておけば前の動画からちょうど繋がる。つまり多少長めのシーケンスを作成できる。

大量のプロンプトとランダムシードで素材を作りまくって(たぶん3000件ぐらいは作ったんじゃないかな)、実際の映像編集は(めんどくさいから)Premiere Proでやりました。でも、振り返るとPythonでやった方が楽だったかもしれない。

まあこんな感じでまだ何件か依頼が来ているのでこなしていく。