AnimateDiffPipeline で Text-to-Video をしていましたが、 AnimateDiffVideoToVideoPipeline を使うと Video-to-Video ができるようになります。
これは Hugging Face のドキュメントに使用方法が載っていましたので触ってみます。
はじめに
何気に Video-to-Video は初めてやるかもしれないです。
なんか前にやったような気がするなぁと思って過去記事を漁ってみましたが、
ControlNet の OpenPose で棒人間動画を使ったくらいかもしれないです。
(どちらにせよ、動画を扱うので似たような感じですが。。。)
AnimateDiffVideoToVideoPipeline を使ってみる
事前準備
インプットとして動画を使うので動画をロードする部分が必要です。
import imageio import requests from io import BytesIO from PIL import Image def load_video(file_path: str): images = [] if file_path.startswith(('http://', 'https://')): # If the file_path is a URL response = requests.get(file_path) response.raise_for_status() content = BytesIO(response.content) frames = imageio.get_reader(content) else: # Assuming it's a local file path frames = imageio.get_reader(file_path) for frame in frames: pil_image = Image.fromarray(frame) images.append(pil_image) return images
画像をロードするときはdiffusers.utilsのload_image()だったけど動画版はないのかな?
動画版OpenPoseのときも imageio 使ってたね。今回は requests モジュールでダウンロードするところからやってるね
モデルのロード等 (MotionAdapter, AnimateDiffVideoToVideoPipeline, DDIMScheduler)
import torch from diffusers import AnimateDiffVideoToVideoPipeline, DDIMScheduler, MotionAdapter # モーションアダプターのロード adapter = MotionAdapter.from_pretrained( "guoyww/animatediff-motion-adapter-v1-5-2", torch_dtype=torch.float16 ) # SD 1.5 系のモデルを AnimateDiffVideoToVideoPipeline でロード pipe = AnimateDiffVideoToVideoPipeline.from_pretrained( "SG161222/Realistic_Vision_V5.1_noVAE", motion_adapter=adapter, torch_dtype=torch.float16 ).to("cuda") # スケジューラの設定 pipe.scheduler = DDIMScheduler.from_config( pipe.scheduler.config, clip_sample=False, timestep_spacing="linspace", beta_schedule="linear", steps_offset=1, ) # enable memory savings pipe.enable_vae_slicing() pipe.enable_model_cpu_offload()
beta_schedule="linear"が付いてる!
インプット用の動画の準備
# 元動画(GIF) init_image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/animatediff-vid2vid-input-1.gif" init_frames = load_video(init_image_url)
動画といいつつ GIF 画像
パイプライン実行
import torch # シード generator = torch.Generator("cuda") generator.seed() # パイプライン実行 prompt = "panda playing a guitar, on a boat, in the ocean, high quality" negative_prompt = "bad quality, worse quality" frames = pipe( video=init_frames, prompt=prompt, negative_prompt=negative_prompt, guidance_scale=7.5, num_inference_steps=25, strength=0.5, generator=generator, ).frames[0]
実行結果
from diffusers.utils import export_to_gif from datetime import datetime from zoneinfo import ZoneInfo # Asia/Tokyo タイムゾーンの現在時刻を YYYYMMDDhhmmss 形式で得る formattedNow = datetime.now(tz=ZoneInfo("Asia/Tokyo")).strftime("%Y%m%d%H%M%S") # 実行結果 export_to_gif(frames, f"animation_{formattedNow}_{generator.initial_seed()}.gif")
ドキュメント通りの出力ではなかったね
strength が 0.5 のせいか、半分くらいパンダになったアライグマ?が出来ました
strength が 0.5 のせいか、半分くらいパンダになったアライグマ?が出来ました
もう1つのサンプル動画でやってみる
まとめ
とりあえず出力できました。