【Stable Video Diffusion】ローカルでの使い方や料金体系、商用利用について解説

Stable-Video-Diffusion

WEELメディア事業部テックリサーチャーの中田です。

11月21日、画像から動画を生成してくれるAI「Stable Video Diffusion」がGitHubで公開され、誰でも「画像を入力とした動画生成」ができるようになりました。

これにより、任意の入力画像に沿った動画の生成が、とても簡単にできるんです…!

GitHubのスター数は、なんと25000を超えており、Stability AIが開発したAIの中でも大注目のプロジェクトです。

この記事ではStable Video Diffusionの使い方や、有効性の検証まで行います。本記事を熟読することで、SVDの凄さを実感し、Image2Videoの魅力にとりつかれるでしょう。

ぜひ、最後までご覧ください。

目次

Stable Video Diffusionの概要

Stable Video Diffusion(SVD)は、Stability AIによって開発されたImage2Videoモデルの一種です。画像生成AIのStable Diffusionをベースに作られており、入力画像から動画を生成できます。

具体的には、これまでStable Diffusionにおいて、プロンプトとしてテキストを入れていた部分に、画像を入力すれば、その画像の内容に即した動画が生成されるのです。

Stable Video Diffusionは、14フレームおよび25フレームを生成できる2種類の画像からビデオへのモデルとしてリリースされており、毎秒3〜30フレームのフレームレートで生成が可能となっています。

参考:https://ja.stability.ai/blog/stable-video-diffusion

簡単に静止画から動きを生み出すことが可能になるため、さまざまなクリエイティブ作業に役立てることができるでしょう。

Stable Video Diffusionの仕組み

Stable Video Diffusionの訓練は、3つの段階に分かれています。

第一段階では、テキストから画像への事前学習です。第二段階は動画の事前学習、第三段階は高品質動画へのファインチューニングという流れで訓練が行われます。

  • 第一段階:テキストから画像への事前学習では、Stable Diffusionの技術を活用して、大規模で多様な画像のデータセットを使って、基本となる空間的特徴を学習します。
  • 第二段階:動画の事前学習では、大量の低解像度動画データを使って、動画の特徴を学習。この際、データはフィルタリングやカット検出で静的シーンや低品質なクリップを除外します。
  • 第三段階:高品質動画へのファインチューニングでは、高解像度かつ高品質の少量のデータセットで微調整を実施。学習には、視覚的に高品質でカメラ動作やキャプションが整合している動画を選択します。

この訓練過程を経ることでStabl Video Diffusionは動画の生成を可能としています。

Stable Diffusion自体、元々は静止画像を生成することに長けています。その技術に「時間的要素」を組み込み、不自然な挙動にならないように学習したデータから前後のフレームの動き方を参照することによって、動画生成が可能です。

一方で、前後のフレームの動き方のみでは、カメラの動きを再現することができません。そこで、Low-Rank Adaptation(LoRA)という技術を使って、カメラの動きをコントロールします。

カメラの水平移動やズームイン、ズームアウトなどを学習させることによって、LoRAでカメラの動きを制御することが可能です。

Stable Video Diffusionのライセンス及び料金体系

非商用利用プロフェッショナルプランエンタープライズプラン
対象者個人利用および研究用年間収益1億円未満、機関投資1億円未満、月間アクティブユーザー100万人未満のクリエイター・開発者向けプロフェッショナルより大規模な企業向け
費用無料月額20ドル カスタム※要問い合わせ
セルフホストモデル 非商用利用商用利用商用利用
特徴・新しいモデルへの早期アクセス・パブリックコミュニティへのアクセス・プロフェッショナル向けDiscordコミュニティ・非商用プランのすべて・カスタム価格・エンタープライズ機能・プロフェッショナルプランのすべて
参考:https://stability.ai/membership

SVDでは、STABLE VIDEO DIFFUSION NON-COMMERCIAL COMMUNITY LICENSE AGREEMENTというライセンスとなっています。

一部を抜粋して日本語に訳したものが下記になります。

Stability AI は、非独占的、全世界的、譲渡不可、サブライセンス不可、取り消し可能なロイヤリティフリーの制限付きライセンスをお客様に付与します。ソフトウェア製品に組み込まれている Stability AI の知的財産または Stability AI が所有するその他の権利に基づいて、商用または生産使用以外の目的でソフトウェア製品の複製、配布、派生作品を作成することはできません。    

基本的には無料で使えますが、無料版だと商用では使えないので注意してください。(詳しくは後述しています)
ライセンスは適宜更新されるようなので利用する前に必ずチェックしておきましょう。

なお、最先端の動画生成AIについて知りたい方はこちらの記事をご覧ください。

Stable Video Diffusionの商用利用は不可能?

Stable Video DiffusionをリリースしたStability AIの発表によると「Stable Video Diffusionは研究用であり、現段階では商用アプリケーションでの使用を意図していない」と書かれています。

現時点では、商用利用はできないようですね。

参考:https://ja.stability.ai/blog/stable-video-diffusion

ただ、2023年12月にStability AIは「顧客が同社のモデルを商業利用する方法を標準化し、有償メンバーシッププランを開始する」と発表しています。有償メンバーシップは収益性とオープン性のバランスをとることを目的としており、ユーザーに商業利用する権利を付与する方法を「再定義」するものとして位置付けられています。

メンバーシップは、

  • Non-Commercial:個人・研究利用向けの無料プラン
  • Professional:機関投資家・クリエイター・開発者・新興企業向けの月額20ドルのプラン
  • Enterprise:Professinalプランよりも大きな顧客向けのカスタムプラン

の3種類が用意されています。

いずれのプランでも、SDXL(Stable Diffusion XL) TurboやStable Video Diffusion・大規模言語モデルの「Stable LM Zephyr 3B」など最新AIモデルへの早期アクセスが提供される予定ですが、商業利用が可能なのはProfessionalプランとEnterpriseプランのみとなるようです。

商用利用したい場合は、有料プランに登録する必要がありそうです。※1

Stable Video Diffusionの使い方

ではStable Video Diffusionを動かすための必要なスペックの紹介と準備をご説明します。

Stable Diffusionのローカルでの使い方はこちら

Stable Video Diffusionを動かすために必要なスペック

今回、Stable Video Diffusionを動かしたのは下記の環境です。

■Google Colab(無料プラン)

GPU:T4

無料プランのT4でもStable Video Diffusionは動かすことができましたが、生成までに時間がかかりました。
メモリが上限に張り付きそうになったしていたため、ギリギリのラインで動いていたようです。

余裕があれば有料のGoogle Colab Proで、GPU:V100、ハイメモリの環境をおすすめします。

Stable Video Diffusionのセットアップ方法

Stable Video Diffusionを試すには様々な方法がありますが、今回は以下のツイートを参考にしました。なお、HuggingFaceのWRITEのトークンが必要になるため事前に準備しておきましょう。

まずは、以下のコードを実行して、Setupを完了させます。

#@title Setup

!nvidia-smi

!git clone https://github.com/Stability-AI/generative-models.git

# install required packages from pypi

# !pip3 install -r generative-models/requirements/pt2.txt

# manually install only necesarry packages for colab

!wget https://gist.githubusercontent.com/mkshing/4ad40699756d996ba6b3f7934e6ca532/raw/3f0094272c7a2bd3eb5f1a0db91bed582c9e8f01/requirements.txt

!pip3 install -r requirements.txt

!pip3 install -e generative-models

!pip3 install -e git+https://github.com/Stability-AI/datapipelines.git@main#egg=sdata

!pip3 install gradio

#@title Colab hack for SVD

# !pip uninstall -y numpy

# !pip install -U numpy

!mkdir -p /content/scripts/util/detection

!ln -s /content/generative-models/scripts/util/detection/p_head_v1.npz /content/scripts/util/detection/p_head_v1.npz

!ln -s /content/generative-models/scripts/util/detection/w_head_v1.npz /content/scripts/util/detection/w_head_v1.npz

次に、HuggingFaceのトークンをセットします。

#@title Login HuggingFace to download weights

#@markdown Please make sure to fill in the form in the model cards and accept it.

from huggingface_hub import login

login()

上記のコードを実行するとトークンを入力するエリアが表示されるので各自で発行したトークンを入力して「Login」をクリックします。

次に、以下のコードを実行して、モデルのcheckpointのダウンロードと、モデルのロードをしましょう。

# @title Download weights

import os

import subprocess

from huggingface_hub import hf_hub_download

version = "svd-xt" #@param ["svd", "svd-xt", "svd-xt-1-1"]

TYPE2PATH = {

    "svd": ["stabilityai/stable-video-diffusion-img2vid", "svd.safetensors"],

    "svd-xt": ["stabilityai/stable-video-diffusion-img2vid-xt", "svd_xt.safetensors"],

    "svd-xt-1-1": ["stabilityai/stable-video-diffusion-img2vid-xt-1-1", "svd_xt_1_1.safetensors"],

}

repo_id, fname = TYPE2PATH[version]

ckpt_dir = "/content/checkpoints"

ckpt_path = os.path.join(ckpt_dir, fname)

# @markdown This will take several minutes. <br>

# @markdown **Reference:**

# @markdown * `svd`: [stabilityai/stable-video-diffusion-img2vid](https://huggingface.co/stabilityai/stable-video-diffusion-img2vid) for 14 frames generation

# @markdown * `svd-xt`: [stabilityai/stable-video-diffusion-img2vid-xt](https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt) for 25 frames generation

# @markdown * `svd-xt-1-1`: [stabilityai/stable-video-diffusion-img2vid-xt-1-1](https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt-1-1) for 25 frames generation with fixed conditioning at 6FPS and Motion Bucket Id 127

os.makedirs("checkpoints", exist_ok=True)

if os.path.exists(ckpt_path):

  print("Already downloaded")

else:

  hf_hub_download(

      repo_id=repo_id,

      filename=fname,

      local_dir=ckpt_dir,

  )

#@title Load Model

import sys

from omegaconf import OmegaConf

import torch

sys.path.append("generative-models")

from sgm.util import default, instantiate_from_config

from scripts.util.detection.nsfw_and_watermark_dectection import DeepFloydDataFiltering

def load_model(

    config: str,

    device: str,

    num_frames: int,

    num_steps: int,

    ckpt_path: str = None,

):

    config = OmegaConf.load(config)

    config.model.params.conditioner_config.params.emb_models[

        0

    ].params.open_clip_embedding_config.params.init_device = device

    config.model.params.sampler_config.params.num_steps = num_steps

    config.model.params.sampler_config.params.guider_config.params.num_frames = (

        num_frames

    )

    if ckpt_path is not None:

        config.model.params.ckpt_path = ckpt_path

        print(f"Changed `ckpt_path` to {ckpt_path}")

    with torch.device(device):

        model = instantiate_from_config(config.model).to(device).eval().requires_grad_(False)

    filter = DeepFloydDataFiltering(verbose=False, device=device)

    return model, filter

if version == "svd":

    num_frames = 14

    num_steps = 25

    # output_folder = default(output_folder, "outputs/simple_video_sample/svd/")

    model_config = "generative-models/scripts/sampling/configs/svd.yaml"

elif "svd-xt" in version:

    num_frames = 25

    num_steps = 30

    # output_folder = default(output_folder, "outputs/simple_video_sample/svd_xt/")

    model_config = "generative-models/scripts/sampling/configs/svd_xt.yaml"

else:

    raise ValueError(f"Version {version} does not exist.")

device = "cuda" if torch.cuda.is_available() else "cpu"

model, filter = load_model(

    model_config,

    device,

    num_frames,

    num_steps,

    ckpt_path,

)

# move models expect unet to cpu

model.conditioner.cpu()

model.first_stage_model.cpu()

# change the dtype of unet

model.model.to(dtype=torch.float16)

torch.cuda.empty_cache()

model = model.requires_grad_(False)

ちなみに、ここで「version」変数の値を「svd_xt」としています。
svdでは14フレーム、svd_xtは25フレームで生成可能なモデルとなっていますので用途に応じたものを選択してください。

なお、より高性能な「svd-xt-1-1」を利用するには住所などを入力し、同意しないと使えませんのでご注意ください。※2

次に、以下のコードを実行して、動画生成を行うための関数を定義します。

# @title Sampling function

import math

import os

from glob import glob

from pathlib import Path

from typing import Optional

import cv2

import numpy as np

import torch

from einops import rearrange, repeat

from fire import Fire

from PIL import Image

from torchvision.transforms import ToTensor

from torchvision.transforms import functional as TF

from sgm.inference.helpers import embed_watermark

from sgm.util import default, instantiate_from_config

def get_unique_embedder_keys_from_conditioner(conditioner):

    return list(set([x.input_key for x in conditioner.embedders]))

def get_batch(keys, value_dict, N, T, device, dtype=None):

    batch = {}

    batch_uc = {}

    for key in keys:

        if key == "fps_id":

            batch[key] = (

                torch.tensor([value_dict["fps_id"]])

                .to(device, dtype=dtype)

                .repeat(int(math.prod(N)))

            )

        elif key == "motion_bucket_id":

            batch[key] = (

                torch.tensor([value_dict["motion_bucket_id"]])

                .to(device, dtype=dtype)

                .repeat(int(math.prod(N)))

            )

        elif key == "cond_aug":

            batch[key] = repeat(

                torch.tensor([value_dict["cond_aug"]]).to(device, dtype=dtype),

                "1 -> b",

                b=math.prod(N),

            )

        elif key == "cond_frames":

            batch[key] = repeat(value_dict["cond_frames"], "1 ... -> b ...", b=N[0])

        elif key == "cond_frames_without_noise":

            batch[key] = repeat(

                value_dict["cond_frames_without_noise"], "1 ... -> b ...", b=N[0]

            )

        else:

            batch[key] = value_dict[key]

    if T is not None:

        batch["num_video_frames"] = T

    for key in batch.keys():

        if key not in batch_uc and isinstance(batch[key], torch.Tensor):

            batch_uc[key] = torch.clone(batch[key])

    return batch, batch_uc

def sample(

    input_path: str = "assets/test_image.png",  # Can either be image file or folder with image files

    resize_image: bool = False,

    num_frames: Optional[int] = None,

    num_steps: Optional[int] = None,

    fps_id: int = 6,

    motion_bucket_id: int = 127,

    cond_aug: float = 0.02,

    seed: int = 23,

    decoding_t: int = 14,  # Number of frames decoded at a time! This eats most VRAM. Reduce if necessary.

    device: str = "cuda",

    output_folder: Optional[str] = "/content/outputs",

    skip_filter: bool = False,

):

    """

    Simple script to generate a single sample conditioned on an image `input_path` or multiple images, one for each

    image file in folder `input_path`. If you run out of VRAM, try decreasing `decoding_t`.

    """

    torch.manual_seed(seed)

    path = Path(input_path)

    all_img_paths = []

    if path.is_file():

        if any([input_path.endswith(x) for x in ["jpg", "jpeg", "png"]]):

            all_img_paths = [input_path]

        else:

            raise ValueError("Path is not valid image file.")

    elif path.is_dir():

        all_img_paths = sorted(

            [

                f

                for f in path.iterdir()

                if f.is_file() and f.suffix.lower() in [".jpg", ".jpeg", ".png"]

            ]

        )

        if len(all_img_paths) == 0:

            raise ValueError("Folder does not contain any images.")

    else:

        raise ValueError

    all_out_paths = []

    for input_img_path in all_img_paths:

        with Image.open(input_img_path) as image:

            if image.mode == "RGBA":

                image = image.convert("RGB")

            if resize_image and image.size != (1024, 576):

                print(f"Resizing {image.size} to (1024, 576)")

                image = TF.resize(TF.resize(image, 1024), (576, 1024))

            w, h = image.size

            if h % 64 != 0 or w % 64 != 0:

                width, height = map(lambda x: x - x % 64, (w, h))

                image = image.resize((width, height))

                print(

                    f"WARNING: Your image is of size {h}x{w} which is not divisible by 64. We are resizing to {height}x{width}!"

                )

            image = ToTensor()(image)

            image = image * 2.0 - 1.0

        image = image.unsqueeze(0).to(device)

        H, W = image.shape[2:]

        assert image.shape[1] == 3

        F = 8

        C = 4

        shape = (num_frames, C, H // F, W // F)

        if (H, W) != (576, 1024):

            print(

                "WARNING: The conditioning frame you provided is not 576x1024. This leads to suboptimal performance as model was only trained on 576x1024. Consider increasing `cond_aug`."

            )

        if motion_bucket_id > 255:

            print(

                "WARNING: High motion bucket! This may lead to suboptimal performance."

            )

        if fps_id < 5:

            print("WARNING: Small fps value! This may lead to suboptimal performance.")

        if fps_id > 30:

            print("WARNING: Large fps value! This may lead to suboptimal performance.")

        value_dict = {}

        value_dict["motion_bucket_id"] = motion_bucket_id

        value_dict["fps_id"] = fps_id

        value_dict["cond_aug"] = cond_aug

        value_dict["cond_frames_without_noise"] = image

        value_dict["cond_frames"] = image + cond_aug * torch.randn_like(image)

        value_dict["cond_aug"] = cond_aug

        # low vram mode

        model.conditioner.cpu()

        model.first_stage_model.cpu()

        torch.cuda.empty_cache()

        model.sampler.verbose = True

        with torch.no_grad():

            with torch.autocast(device):

                model.conditioner.to(device)

                batch, batch_uc = get_batch(

                    get_unique_embedder_keys_from_conditioner(model.conditioner),

                    value_dict,

                    [1, num_frames],

                    T=num_frames,

                    device=device,

                )

                c, uc = model.conditioner.get_unconditional_conditioning(

                    batch,

                    batch_uc=batch_uc,

                    force_uc_zero_embeddings=[

                        "cond_frames",

                        "cond_frames_without_noise",

                    ],

                )

                model.conditioner.cpu()

                torch.cuda.empty_cache()

                # from here, dtype is fp16

                for k in ["crossattn", "concat"]:

                    uc[k] = repeat(uc[k], "b ... -> b t ...", t=num_frames)

                    uc[k] = rearrange(uc[k], "b t ... -> (b t) ...", t=num_frames)

                    c[k] = repeat(c[k], "b ... -> b t ...", t=num_frames)

                    c[k] = rearrange(c[k], "b t ... -> (b t) ...", t=num_frames)

                for k in uc.keys():

                    uc[k] = uc[k].to(dtype=torch.float16)

                    c[k] = c[k].to(dtype=torch.float16)

                randn = torch.randn(shape, device=device, dtype=torch.float16)

                additional_model_inputs = {}

                additional_model_inputs["image_only_indicator"] = torch.zeros(

                    2, num_frames

                ).to(device, )

                additional_model_inputs["num_video_frames"] = batch["num_video_frames"]

                for k in additional_model_inputs:

                    if isinstance(additional_model_inputs[k], torch.Tensor):

                        additional_model_inputs[k] = additional_model_inputs[k].to(dtype=torch.float16)

                def denoiser(input, sigma, c):

                    return model.denoiser(

                        model.model, input, sigma, c, **additional_model_inputs

                    )

                samples_z = model.sampler(denoiser, randn, cond=c, uc=uc)

                samples_z.to(dtype=model.first_stage_model.dtype)

                ##

                model.en_and_decode_n_samples_a_time = decoding_t

                model.first_stage_model.to(device)

                samples_x = model.decode_first_stage(samples_z)

                samples = torch.clamp((samples_x + 1.0) / 2.0, min=0.0, max=1.0)

                model.first_stage_model.cpu()

                torch.cuda.empty_cache()

                os.makedirs(output_folder, exist_ok=True)

                base_count = len(glob(os.path.join(output_folder, "*.mp4")))

                video_path = os.path.join(output_folder, f"{base_count:06d}.mp4")

                writer = cv2.VideoWriter(

                    video_path,

                    cv2.VideoWriter_fourcc(*"MP4V"),

                    fps_id + 1,

                    (samples.shape[-1], samples.shape[-2]),

                )

                samples = embed_watermark(samples)

                if not skip_filter:

                    samples = filter(samples)

                else:

                    print("WARNING: You have disabled the NSFW/Watermark filter. Please do not expose unfiltered results in services or applications open to the public.")

                vid = (

                    (rearrange(samples, "t c h w -> t h w c") * 255)

                    .cpu()

                    .numpy()

                    .astype(np.uint8)

                )

                for frame in vid:

                    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

                    writer.write(frame)

                writer.release()

                all_out_paths.append(video_path)

    return all_out_paths

最後に、以下のコードを実行してください。

# @title Do the Run!

# @markdown Generation takes about 10 mins for 25 frames on T4 (Colab free plan). Please be patient...

# @markdown (V100 takes about 3 mins.)

import gradio as gr

import random

def infer(input_path: str, resize_image: bool, n_frames: int, n_steps: int, seed: str, decoding_t: int, fps_id: int, motion_bucket_id: int, cond_aug: float, skip_filter: bool = False) -> str:

  if seed == "random":

    seed = random.randint(0, 2**32)

  if version == "svd-xt-1-1":

    if fps_id != 6:

      print("[WARNING] svd-xt-1-1 was fine-tuned in fixed conditioning (`fps_id=6`, `motion_bucket_id=127`)! The performance may vary compared to SVD 1.0.")

    if motion_bucket_id != 127:

      print("[WARNING] svd-xt-1-1 was fine-tuned in fixed conditioning (`fps_id=6`, `motion_bucket_id=127`)! The performance may vary compared to SVD 1.0.")

  seed = int(seed)

  output_paths = sample(

    input_path=input_path,

    resize_image=resize_image,

    num_frames=n_frames,

    num_steps=n_steps,

    fps_id=fps_id,

    motion_bucket_id=motion_bucket_id,

    cond_aug=cond_aug,

    seed=seed,

    decoding_t=decoding_t,  # Number of frames decoded at a time! This eats most VRAM. Reduce if necessary.

    device=device,

    skip_filter=skip_filter,

  )

  return output_paths[0]

with gr.Blocks() as demo:

  with gr.Column():

    image = gr.Image(label="input image", type="filepath")

    resize_image = gr.Checkbox(label="resize to optimal size", value=True)

    btn = gr.Button("Run")

    with gr.Accordion(label="Advanced options", open=False):

      n_frames = gr.Number(precision=0, label="number of frames", value=num_frames)

      n_steps = gr.Number(precision=0, label="number of steps", value=num_steps)

      seed = gr.Text(value="random", label="seed (integer or 'random')",)

      decoding_t = gr.Number(precision=0, label="number of frames decoded at a time", value=2)

      fps_id = gr.Number(precision=0, label="frames per second", value=6)

      motion_bucket_id = gr.Number(precision=0, value=127, label="motion bucket id")

      cond_aug = gr.Number(label="condition augmentation factor", value=0.02)

      skip_filter = gr.Checkbox(value=False, label="skip nsfw/watermark filter")

  with gr.Column():

    video_out = gr.Video(label="generated video")

  examples = [

      ["https://user-images.githubusercontent.com/33302880/284758167-367a25d8-8d7b-42d3-8391-6d82813c7b0f.png"],

  ]

  inputs = [image, resize_image, n_frames, n_steps, seed, decoding_t, fps_id, motion_bucket_id, cond_aug, skip_filter]

  outputs = [video_out]

  btn.click(infer, inputs=inputs, outputs=outputs)

  gr.Examples(examples=examples, inputs=inputs, outputs=outputs, fn=infer)

  demo.queue().launch(debug=True, share=True, show_error=True)

上記を実行すると、以下のような画面が出てくると思います。

「ここに画像をドロップ」のところに任意の画像をアップロードして、「Run」をクリックすると、動画が生成されます。

Stable Video Diffusionを実際に使ってみた

ここでは、冒頭の導入文にある、以下の画像を動画化してみましょう。

アップロードして、SVDで動かしてみた結果が、以下の通りです。

なんか、角度が変化しているだけに感じます。

お次はSVD-XT。

うーん、クオリティは悪くないんだけど、なんかカクカクしています。

なお、ByteDanceが開発した動画生成AIについて知りたい方はこちらの記事をご覧ください。

Stable Video Diffusionの推しポイントである高品質な動画生成は本当なのか?

Stable Video Diffusionの威力を確かめるために、Runwayの「Gen-2」と比較してみます。

そこで、先ほどのStable Video Diffusionへのタスクを、Gen-2にも行わせて、品質を比較してみようと思います。Gen-2は、以下のページから利用できます。

Gen-2: The Next Step Forward for Generative AI

Gen-2によって生成された動画は、以下の通りです。

細部までかなり自然ですね!ただ、人の手が歪んでいたりして、不自然な部分も見受けられました。

とはいえ、SVDよりもGen-2の方が、まだまだ精度がよさそうです。

注意点

Stable Video Diffusionを使う上での注意点は次の2つです。

  • GPUの使いすぎ
  • 著作権

Stable Video Diffusionを使う際に、google colaboratoryで実装される時にはGPUの使いすぎに注意が必要です。動画を生成するにはかなりの時間がかかり、google colaboratoryは時間経過に応じてリソースが消費されます。

そのため、気づいたらリソースが空になってしまったということにならないように、注意しましょう。

また、Stable Video Diffusionで生成された動画の著作権自体は問題ありませんが、使用した画像に関しては著作権の問題が発生することがあります。

クリエイターが作成した画像を使ってしまった、企業のロゴやキャラクターの画像を使って動画を生成してしまった、ということにならないよう、元の画像の著作権については注意しておくのがいいでしょう。

活用事例

今回解説する事例において、弊社がX(旧Twitter)で発見した参考となるツイートを紹介させていただいております。取り下げなどのご連絡は、contact@weel.co.jp からご連絡ください。

Stable Diffusionを使った事例として、コカコーラのCMがあります。

KDDIのCMでもStable Diffusionが活用されています。

近年では、CMに生成AIを活用する事例が増えてきており、今後もますます増加すると考えられます。

生成AIを使ってCMを作ることで、コストが下がり、生成AIを使わなかったときに比べて短時間で作成することができます。

また、非現実的な映像を実現することもできるので、視聴者に対してよりインパクトを与えることも可能。

StableVideo Diffusionに関するQ&A

ここではStable Video Diffusionを使う上で、よくある質問をまとめておきます。

Q1:Stable Video Diffusionでどのような動画が生成できますか?

A1:プロンプトからの動画生成や静止画を元にした動画生成が可能です。

Q2:Stable Video Diffusionを使うのに必要なパソコンのスペックは?

A2:RTX30シリーズや40シリーズのGPU、VRAMは16GB以上が望ましいです。google colaboratoryで動かす場合には、T4でも可能ですがやはりA100の方が生成時間は短縮できます。

Q3:動画生成にはどのくらいの時間かかりますか?

A3:動画の長さや解像度、フレーム数、GPUによって異なりますが、1秒間に24フレームの動画を生成する場合には、数分から数時間です。

Q4:Stable Video Diffusionは商用利用可能?

A4:商用利用する場合にはprofessional以上のプランに契約する必要があります.

Q5:動画の解像度は指定できますか?

A5:指定できます。解像度を高くすればするだけ、生成時間はかかります。

Q6.モデルがロードされません

A6.モデルのファイルが見つからないか破損している、指定したバージョンと異なっている場合があります。正しいパスとバージョンを確認、再ダウンロードを試してください。

Q7.CUDA Out of Memoryと表示されます。

A7.メモリ不足です。入力解像度が高すぎたりフレーム数が多い、GPUメモリが少ない場合に生じます。解像度やフレーム数を下げる、バッチサイズを減らすなどで対応をしましょう。

Q8.フレーム生成の途中で処理が止まります。

A8.VRAM不足が考えられるので、フレーム数を減らして再度生成してみてください。

StableVideo Diffusionで簡単に静止画から動画を生成してみましょう

Stable Video Diffusion(SVD)は、Stability AIによって開発されたImage2Videoモデルの一種で、入力画像から動画を生成できます。

誰でも無料で利用可能できるAIツールであり、画像を入力すれば、その画像の内容に即した動画が生成されるのです。使い方は簡単で、本記事のコードをそのまま実行すれば、実行できます。

実際に試したところ、角度が動いているだけだったり、カクカクしていたりしました。加えて、比較検証したところ、やはりSVDよりもGen-2の方が、まだまだ精度がよさそうです。

数年後には、『アーサー・C・クラークの小説』のように、誰でもアーティストになれる時代が来るかもしれないですね。

サービス紹介資料

生成系AIの業務活用なら!

・生成系AIを活用したPoC開発

・生成系AIのコンサルティング

・システム間API連携

最後に

いかがだったでしょうか?

Stable Video Diffusionの登場により、静止画から動画生成のハードルが大きく下がりました。ビジュアルコンテンツ制作の新たな可能性を、貴社のプロダクトや事業にどう活かせるか、最適な活用方法を検討してみましょう。

株式会社WEELは、自社・業務特化の効果が出るAIプロダクト開発が強みです!

開発実績として、

・新規事業室での「リサーチ」「分析」「事業計画検討」を70%自動化するAIエージェント
・社内お問い合わせの1次回答を自動化するRAG型のチャットボット
・過去事例や最新情報を加味して、10秒で記事のたたき台を作成できるAIプロダクト
・お客様からのメール対応の工数を80%削減したAIメール
・サーバーやAI PCを活用したオンプレでの生成AI活用
・生徒の感情や学習状況を踏まえ、勉強をアシストするAIアシスタント

などの開発実績がございます。

まずは、無料相談にてご相談を承っておりますので、ご興味がある方はぜひご連絡ください。

➡︎生成AIを使った業務効率化、生成AIツールの開発について相談をしてみる。

生成AIを社内で活用していきたい方へ
無料相談

「生成AIを社内で活用したい」「生成AIの事業をやっていきたい」という方に向けて、生成AI社内セミナー・勉強会をさせていただいております。

セミナー内容や料金については、ご相談ください。

また、サービス紹介資料もご用意しておりますので、併せてご確認ください。

投稿者

  • 中田

    データサイエンス専攻の大学院生。大学では、生成系AIの拡散モデルを用いた音楽生成について研究。 趣味は作曲、サッカー、コーヒー。

  • URLをコピーしました!
  • URLをコピーしました!
目次