Supershipの名畑です。魔神英雄伝ワタルの新作テレビアニメ制作決定のニュースは新年早々熱すぎますね。
はじめに
少し前にはなりますが、Stable Diffusionの提供元であるstability.aiより興味深い情報が発信されていました。
・Developer Platform APIに、ビデオ生成の基盤モデルであるStable Video Diffusionを追加しました。
・モデルは、平均41秒以内に、25フレームの生成フレームと24フレームのFILM補間からなる2秒間のビデオを生成することができます。
・APIを通じたStable Video Diffusionの活用に関心のある開発者は、Stability AI Developer Platformで今すぐアクセスできます。参考:Stability AI Developer Platform APIでStable Video Diffusionが利用可能になりました
つまりは、静止画を元にした2秒間の動画生成をWeb API経由で行えるようになったということ。
これを実際に試してみましたというのが今回の記事の内容となります。
実装にはPythonを用いています。
注意
私はとりあえず試してみたかったのでWeb API経由で呼び出してみましたが、ローカルで動かせます。
Stable Video Diffusionについて詳しくは下記の情報をご覧ください。
自環境
macOS(Venture)です。
Pythonはすでにインストール済みです。
$ python --version
Python 3.10.12
また、requestsを用いるためインストールしておきました。
$ pip install requests
今のバージョンは2.31.0でした。
$ pip show requests
Name: requests
Version: 2.31.0
以下略
アカウント作成
Developer PlatformのLoginを押すと、下部にDon't have an account? Sign upの記載がありますので、こちらからアカウント作成が可能です。
Google、あるいは、メールアドレスでのアカウント作成に対応しています。
API key発行
ログイン後のAccountのページで行えます。
取得したAPI keyはハードコーディングを避けるため環境変数に設定しました。
STABILITY_API_KEYという環境変数名としました。
export STABILITY_API_KEY =ここに取得したAPI keyを書く
価格
Pricing Tableに価格が掲載されています。
現在は1動画生成につき $0.2 のようです。$1を150円とすると30円ですね。
元画像
過去記事「Stable Diffusionの最新モデル「SDXL 1.0」と過去モデルの生成画像をひたすら比較して進化を実感してみた」で生成した画像を選びました。
API仕様として、画像サイズは1024x576、576x1024、768x768のいずれか、画像フォーマットはimage/jpeg、image/pngのいずれかとのことなので、今回は768x768のPNG画像としました。
Pythonでのコード
v2alpha/generationのAPI referenceを参考にして実装しました。
まず生成のAPIであるimage-to-videoを呼び出し、それから一定時間後に結果取得用のAPIであるimage-to-video/resultを呼び出しています。
元画像ファイルはこのコードと同一階層にoriginal_image.pngというファイル名で保存してあります。
import requests
import os
import base64
import time
api_key = os.getenv("STABILITY_API_KEY")
api_host = 'https://api.stability.ai'
original_image = "original_image.png" # 画像ファイル名
seed = 0 # シード値(0〜2147483648)
cfg_scale = 2.5 # 画像にどれだけ忠実とするか(0〜10)
motion_bucket_id = 40 # 動画の動きの大きさ(1〜255)
# 生成API呼び出し
params = {
"seed": seed,
"cfg_scale": cfg_scale,
"motion_bucket_id": motion_bucket_id,
}
file = {
"image": (original_image, open(original_image, 'rb'), 'image/png'),
}
headers = {
"Authorization": f"Bearer {api_key}"
}
response = requests.post(
f"{api_host}/v2alpha/generation/image-to-video",
headers=headers,
files=file,
data=params
)
if response.status_code != 200: # 失敗
print(response.json())
exit()
response_id = response.json()['id']
print(response_id)
# 結果取得API呼び出し 60秒間隔で3度確認
count = 0
while count < 3:
count += 1
time.sleep(60)
headers["accept"] = "application/json"
response = requests.get(
f"{api_host}/v2alpha/generation/image-to-video/result/{response_id}",
headers=headers
)
if response.status_code == 200: # 成功
# 動画の保存
with open(f"./{int(time.time())}_seed_{seed}_cs_{cfg_scale}_mbi_{motion_bucket_id}.mp4", "wb") as f:
f.write(base64.b64decode(response.json()["video"]))
break
else: # 失敗
print(response.json())
生成時に指定可能なパラメータは画像(image)を除くと下記の3つです。
- seed:シード値(0〜2147483648)
- cfg_scale:画像にどれだけ忠実とするか(0〜10)
- motion_bucket_id:動画の動きの大きさ(1〜255)
現時点ではアルファ版ということもあってなのか「どんな動きをさせるか」は指定できないため、これらのパラメータを動かして狙った動画を生成するしかなさそうです。
生成結果
実際の生成物はmp4ですが、アニメーションGIFにしたものを掲載しておきます。
容量の関係で画質は落としてあります。ですので実際はもっと鮮明です。
パラメータを少しいじってみる
seed = 0
cfg_scale = 2.5
motion_bucket_id = 255
motion_bucket_idを255にしてみました。
変化をはっきりさせたいために最大値を指定しました。
生成結果は以下です。
確かに動きが大きくなっています。
最後に
生成された動画がかなり自然ですね。
今年も1年が終わる頃にはかなりの変化が訪れていそうと実感します。
宣伝
SupershipのQiita Organizationを合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。
Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方はSupership株式会社 採用サイトよりご確認ください。