【Google Colab】Text2Video-ZeroとAnything v4.0を用いて,テキストからアニメ動画を生成してみた

はじめに

先日の記事「【Paperspace Gradient】Text2Video-ZeroとAnything v4.0を用いて,テキストからアニメ動画を生成してみた」をGoogle Colabでも同じことをやってみた.

私はPaperspaceユーザーとなり,現在Colabは無料版のアカウントである.そのため,T4しか使えない.その場合,上記の記事と同様のコードだとVRAM不足で動かない.

Token Merging というVRAMを削減する機能が組み込まれていたようなので,本記事ではその設定を行うことで,T4上で動作させた.

ちなみに,gradioを使うバージョンは,以下にコードがあったので,これを使っても良いかも.Anything v4.0が使えるかは不明である.

GitHub - camenduru/text2video-zero-colab
Contribute to camenduru/text2video-zero-colab development by creating an account on GitHub.

方法

まずはGoogle Driveをマウントする.Paperspaceではtmpディレクトリを使ったが,ColabではGoogle Driveをワークスペースにした.

from google.colab import drive
drive.mount('/content/drive')

次にText2Video-Zeroのリポジトリのダウンロード,および必要なライブラリのインストールを行った.

%cd /content/drive/MyDrive
!git clone https://github.com/Picsart-AI-Research/Text2Video-Zero.git
%cd Text2Video-Zero/

# !pip install -r requirements.txt
!pip install -q gradio==3.23.0 decord==0.6.0 diffusers==0.14.0 accelerate==0.17.0 safetensors==0.2.7 einops==0.6.0 transformers==4.26.0
!pip install -q torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 torchtext==0.14.1 torchdata==0.5.1 --extra-index-url https://download.pytorch.org/whl/cu116 -U
!pip install -q xformers==0.0.16 triton==2.0.0 -U
!pip install -q kornia==0.6 tomesd basicsr==1.4.2 timm==0.6.12

次にmodel.pyを修正する.ここはpaperspaceの場合と同じである.

model.pyをコピペして,process_text2video関数を以下のように書き換える.下記のコードの最初にある「%%file model.py」でファイルを生成して,model.pyを上書きしている.inference関数の引数で,「chunk_size=2」と設定することによりVRAMの消費を抑えることが可能となる.

%%file model.py
from enum import Enum
import gc
import numpy as np
import tomesd
import torch

~~省略~~

    def process_text2video(self, prompt,model_name,added_prompt,negative_prompts,guidance_scale,num_inference_steps,path,fps,t0,t1,motion_field_strength_x,motion_field_strength_y,video_length,chunk_size=8,watermark='Picsart AI Research',merging_ratio=0.0,seed=-1,
resolution=512,use_cf_attn=True,use_motion_field=True,smooth_bg=False,smooth_bg_strength=0.4):
        print("Module Text2Video")
        if self.model_type != ModelType.Text2Video or model_name != self.model_name:
            print("Model update")
            unet = UNet2DConditionModel.from_pretrained(
                model_name, subfolder="unet")
            self.set_model(ModelType.Text2Video,
                           model_id=model_name, unet=unet)
            self.pipe.scheduler = DDIMScheduler.from_config(
                self.pipe.scheduler.config)
            if use_cf_attn:
                self.pipe.unet.set_attn_processor(
                    processor=self.text2video_attn_proc)
        self.generator.manual_seed(seed)

        # added_prompt = "masterpiece, best quality, masterpiece"
        # negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer difits, cropped, worst quality, low quality, deformed body, bloated, ugly, unrealistic'

        prompt = prompt.rstrip()
        if len(prompt) > 0 and (prompt[-1] == "," or prompt[-1] == "."):
            prompt = prompt.rstrip()[:-1]
        prompt = prompt.rstrip()
        prompt = prompt + ", "+added_prompt
        # if len(n_prompt) > 0:
        #     negative_prompt = n_prompt
        # else:
        #     negative_prompt = None
        

        result = self.inference(prompt=prompt,
                                video_length=video_length,
                                height=resolution,
                                width=resolution,
                                num_inference_steps=num_inference_steps,
                                guidance_scale=guidance_scale,
                                guidance_stop_step=1.0,
                                t0=t0,
                                t1=t1,
                                motion_field_strength_x=motion_field_strength_x,
                                motion_field_strength_y=motion_field_strength_y,
                                use_motion_field=use_motion_field,
                                smooth_bg=smooth_bg,
                                smooth_bg_strength=smooth_bg_strength,
                                seed=seed,
                                output_type='numpy',
                                negative_prompt=negative_prompts,
                                merging_ratio=merging_ratio,
                                split_to_chunks=True,
                                chunk_size=2
                                )
        return utils.create_video(result, fps, path=path, watermark=None)

最後に,以下のコードを実行して動画を生成する.各変数はPaperspaceの場合と同じである.コードもほとんど同じであるが,ワークスペースがgoogle driveなので,それを指定する.動画は,「/content/drive/MyDrive/Text2Video-Zero/outputs」ディレクトリに保存される.

%mkdir /content/drive/MyDrive/Text2Video-Zero/outputs #Google Driveに出力動画の保存先を作る
%cp /content/drive/MyDrive/Text2Video-Zero/model.py /content/ #model.pyをcontentディレクトリにもってくる.

#model.pyを再読み込み(model.pyは頻繁に修正する可能性があるが,再読み込みしないと修正が反映されない)
import model
from importlib import reload
reload(model)

import torch
from model import Model

model = Model(device = "cuda", dtype = torch.float16)

#メインプロンプト(キャラクターの動作を記述する)
prompt = "a dog running on a seaside"

#追加のプロンプト(best qualityなどの修飾)
added_prompt = "masterpiece, best quality, masterpiece"

#ネガティブプロンプト
negative_prompts = "longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer difits, cropped, worst quality, low quality, deformed body, bloated, ugly, unrealistic"

#hugging faceのリポジトリの指定(例えばSD1.5であれば,"runwayml/stable-diffusion-v1-5"を指定する)
model_name=r"andite/anything-v4.0"

#ガイダンススケール
guidance_scale=7.5 #default:7.5

#サンプリングステップ数. t1の値を超えるとエラーになる(というか50以下だとエラーになる).
num_inference_steps=50 #default:50

#出力する動画の名前
out_path = f"/content/drive/MyDrive/Text2Video-Zero/outputs/text2video_{prompt.replace(' ','_')}.mp4"

#その他のパラメータ
fps=4 #FPS default:4
t0= 44 #default:44. 詳細は不明.44の場合,timestepsでは881に相当するらしい.timesteps換算でt1-t0が60の時が,経験的に一番いい感じだったと論文には書いてあった.
t1= 47 #default:47. 詳細は不明.47の場合,timestepsでは941に相当するらしい.
motion_field_strength_x = 12 #default:12. the globalscene and camera motionのパラメータらしい.が,motionの大きさに関連している?
motion_field_strength_y = 12 #default:12
video_length=8 #default:8. 動画の長さ

# 動画の生成
model.process_text2video(prompt,model_name,added_prompt,negative_prompts,guidance_scale,num_inference_steps,out_path,fps, t0, t1, motion_field_strength_x, motion_field_strength_y, video_length)

# ダウンロードしたモデルの場所は以下のコマンドで確認.
# find / -name "*model.safetensors"

得られた動画

なぜかPaperspaceで実行したときよりも,一貫性がある気がする.偶然だろうか?

まとめ

Colab無料バージョンのT4環境下でも動かすことができた.

ColabではまだFILMは試してないが,実行速度が大変なことになりそうなので,重い処理はPaperspace Gradient Growthの方に任せたい.

コメント

タイトルとURLをコピーしました