🐷

Beyond LLM > 動画生成AIモデルの基礎を知る

に公開

動画生成AIモデルの基礎を知る

2.1 ComfyUIワークフローから理解する動画生成

2.1.1 動画生成ワークフローの全体像

ComfyUIで動画を生成する際、以下のような複雑な接続図を目にします:

[Checkpoint Loader] → [CLIP Text Encode] → [KSampler] → [VAE Decode] → [Save Video]
       ↓                     ↓                  ↓
[ControlNet Loader]    [IP-Adapter]      [AnimateDiff]
       ↓                     ↓                  ↓
   [Processor]          [Image Encoder]    [Motion Module]

一見複雑ですが、これらはプログラミングの制御構造に似た役割を持っています:

  • ControlNet: 条件分岐(if文)のように「この構造に従え」と指示
  • IP-Adapter: 参照(import)のように「この画像の特徴を使え」と指示
  • AnimateDiff: ループ(for文)のように「フレーム間の動きを生成せよ」と指示
  • LoRA: パラメータ調整(引数)のように「このスタイルを適用せよ」と指示

本章では、各モジュールがなぜ必要か、どう組み合わせるかを理解していきます。

2.2 動画生成AIの基本構造

2.2.1 コアアーキテクチャ

動画生成の基本フローは以下の3段階です:

入力 → 処理 → 出力
(テキスト/画像) → (拡散プロセス) → (動画フレーム)

具体的には:

[1] テキストエンコーダ(CLIP/T5)
    ↓ プロンプトを数値ベクトルに変換
[2] U-Net + 時間的アテンション
    ↓ ノイズ除去 + フレーム間の整合性維持
[3] VAE(変分オートエンコーダ)
    ↓ 潜在空間から画像空間へ変換
[4] 出力(動画フレーム列)

2.2.2 なぜこんなに複雑なのか?

動画生成には3つの大きな課題があります:

1. 時間的一貫性の維持
→ AnimateDiffが解決

2. 生成内容の制御
→ ControlNet、IP-Adapterが解決

3. スタイルの適用
→ LoRAが解決

これらを理解すれば、ワークフローの接続の意味が見えてきます。

2.3 AnimateDiff: 時間をつなぐモジュール

2.3.1 AnimateDiffの役割

問題: 画像生成モデル(Stable Diffusion)は静止画しか作れない

解決: AnimateDiffが「時間的アテンション層」を追加

# 概念的なコード
for frame in video_frames:
    current_frame = generate_image(prompt)
    # ここで前後のフレームを参照して一貫性を保つ
    current_frame = temporal_attention(current_frame, previous_frames)

2.3.2 なぜ必要か

AnimateDiffがないと:

  • ✗ 各フレームが独立して生成される
  • ✗ オブジェクトの位置がバラバラ
  • ✗ フリッカリング(ちらつき)が発生

AnimateDiffがあると:

  • ✓ フレーム間で情報を共有
  • ✓ 滑らかな動きを生成
  • ✓ オブジェクトの一貫性を維持

2.3.3 ComfyUIでの接続

[Load Checkpoint]
    ↓
[AnimateDiff Loader] ← Motion Moduleを読み込む
    ↓
[KSampler] ← 時間的アテンションが有効化される

プログラミングの例え:

# AnimateDiffなし(16枚の独立した画像)
for i in range(16):
    frame[i] = generate_image(prompt)

# AnimateDiffあり(16フレームの動画)
video = generate_video_with_motion(prompt, frames=16)

2.4 ControlNet: 構造を制御するモジュール

2.4.1 ControlNetの役割

問題: テキストプロンプトだけでは細かい構造を指定できない

解決: ControlNetが「構造情報」を追加で与える

テキスト: "人が歩いている"
     +
ControlNet(Pose): 人のポーズ情報
     ↓
指定したポーズで人が歩く動画

2.4.2 なぜ必要か

プロンプトだけでは:

  • ✗ 「右手を上げて」が反映されない
  • ✗ カメラワークが思い通りにならない
  • ✗ 物体の配置が制御できない

ControlNetを使うと:

  • ✓ ポーズを正確に指定(OpenPose)
  • ✓ 奥行きを制御(Depth)
  • ✓ 輪郭を保持(Canny)
  • ✓ 動きを指定(Optical Flow)

2.4.3 ControlNetの種類

動画生成でよく使うもの:

ControlNet 用途 プログラミングの例え
OpenPose ポーズ制御 if (pose == "walking")
Depth 奥行き制御 if (distance > 5m)
Canny 輪郭保持 if (edge_detected)
Optical Flow 動き制御 for motion in directions

2.4.4 ComfyUIでの接続

[Load ControlNet Model]
    ↓
[Apply ControlNet] ← 条件を追加
    ↓           ↑
[KSampler]    [Preprocessor] ← 入力画像/動画を処理

条件分岐のイメージ:

if controlnet_type == "depth":
    生成時に奥行き情報を考慮する
elif controlnet_type == "pose":
    生成時にポーズ情報を考慮する

2.5 IP-Adapter: 画像の特徴を参照するモジュール

2.5.1 IP-Adapterの役割

問題: 「このキャラクターと同じ見た目で動画を作りたい」がプロンプトでは表現困難

解決: IP-Adapterが参照画像の特徴を抽出して適用

参照画像: character.png
     ↓ IP-Adapter
生成動画: その見た目を保ったまま動く

2.5.2 なぜ必要か

プロンプトの限界:

  • ✗ 「赤い服を着た長い髪の女性」では曖昧
  • ✗ 同じキャラクターの再現が困難
  • ✗ 細部の特徴が伝わらない

IP-Adapterで:

  • ✓ 画像1枚で見た目を指定
  • ✓ キャラクター一貫性が向上
  • ✓ スタイルの転写が可能

2.5.3 ComfyUIでの接続

[Load IP-Adapter]
    ↓
[IP-Adapter Apply] ← 画像の特徴を注入
    ↓           ↑
[KSampler]    [Reference Image] ← 参照画像

プログラミングの例え:

# import文のように外部の特徴を取り込む
from reference_image import style, character_features
generate_video(prompt, style=style, character=character_features)

2.6 LoRA: スタイルを適用するモジュール

2.6.1 LoRAの役割

問題: ベースモデルでは表現できないスタイル(アニメ風、特定の画風など)

解決: LoRAが追加学習した「スタイルパラメータ」を適用

ベースモデル
    +
LoRA(アニメ風)
    ↓
アニメスタイルの動画

2.6.2 なぜ必要か

ベースモデルだけでは:

  • ✗ 特定のアーティストのスタイルが出せない
  • ✗ 細かいニュアンスが不足
  • ✗ 全体的に平凡な出力

LoRAを使うと:

  • ✓ 特定のスタイルを強化(アニメ、油絵、水彩画など)
  • ✓ キャラクターの再現性向上
  • ✓ 小さいファイルサイズで多様な表現

2.6.3 ComfyUIでの接続

[Load LoRA] ← スタイル定義ファイル
    ↓
[Model] ← パラメータが調整される
    ↓
[KSampler] ← 調整されたモデルで生成

プログラミングの例え:

# 関数の引数のようにスタイルを渡す
def generate_video(prompt, lora_style="anime", lora_weight=0.8):
    model = base_model + lora_style * lora_weight
    return model.generate(prompt)

2.7 潜在空間(Latent Space): 効率化の鍵

2.7.1 なぜ潜在空間を使うのか

問題: 動画を直接ピクセルで処理すると計算量が膨大

フルHD 16フレーム動画
= 1920 × 1080 × 3色 × 16フレーム
= 約1億次元のデータ

解決: VAEで圧縮した潜在空間で処理

潜在空間での同じ動画
= 128 × 72 × 4チャンネル × 16フレーム
= 約59万次元(1/170に圧縮)

2.7.2 VAEの役割

[VAE Encode] 画像 → 潜在空間(圧縮)
     ↓
[処理](KSampler等で高速に処理)
     ↓
[VAE Decode] 潜在空間 → 画像(復元)

プログラミングの例え:

# データ圧縮のようなイメージ
compressed_data = compress(raw_video)  # VAE Encode
processed_data = process(compressed_data)  # 処理
final_video = decompress(processed_data)  # VAE Decode

2.8 時間的一貫性(Temporal Coherence)

2.8.1 なぜ重要か

動画で最も重要な概念。フレーム間で以下を維持する必要があります:

  • オブジェクトのアイデンティティ(猫は猫のまま)
  • 照明の一貫性(急に暗くならない)
  • 背景の安定性(建物が消えない)
  • 動きの滑らかさ(テレポートしない)

崩れると起きる問題:

  • フリッカリング(ちらつき)
  • ドリフティング(徐々に別物に変化)
  • モーフィング(形が歪む)

2.8.2 各モジュールの貢献

AnimateDiff: フレーム間のアテンションで一貫性維持
ControlNet: 構造的一貫性を保証
IP-Adapter: 見た目の一貫性を保証

2.9 モジュールの組み合わせ戦略

2.9.1 基本的な組み合わせパターン

パターン1: 最小構成

Checkpoint → AnimateDiff → KSampler → VAE Decode
(動くが制御は弱い)

パターン2: 構造制御

Checkpoint → AnimateDiff + ControlNet → KSampler → VAE
(ポーズや構図を制御)

パターン3: 見た目制御

Checkpoint → AnimateDiff + IP-Adapter → KSampler → VAE
(キャラクターの一貫性)

パターン4: フル制御

Checkpoint → AnimateDiff + ControlNet + IP-Adapter + LoRA → KSampler → VAE
(最大限の制御)

2.9.2 選択基準

目的 必要なモジュール
ただ動画を作りたい AnimateDiff
ポーズを指定したい + ControlNet(OpenPose)
キャラを統一したい + IP-Adapter
アニメ風にしたい + LoRA
全部制御したい 全部使う

2.10 生成方式の種類

Text-to-Video

テキストのみから生成

  • 最も自由度が高い
  • 制御は難しい

Image-to-Video

画像から動きをつける

  • 開始フレームが固定
  • Stable Video Diffusionが代表的

Video-to-Video

動画を別スタイルに変換

  • 元の構造を維持
  • スタイル転送に最適

2.11 まとめ

ComfyUIワークフローの見方

各モジュール = プログラミングの制御構造

AnimateDiff  = for文(フレームをループ)
ControlNet   = if文(条件で制御)
IP-Adapter   = import文(外部特徴を参照)
LoRA         = 引数(パラメータ調整)
VAE          = 圧縮/解凍(効率化)

今後の展望と書籍のご紹介

フィジカルAIと世界モデルの発展により、AIは単なる情報処理システムから、物理世界を理解し、相互作用できる存在へと進化しつつあります。
この技術の進展は、ロボティクス、自動運転、製造業、さらにはエンターテインメント分野まで、幅広い産業に革新をもたらす可能性を秘めています。
この記事では、世界モデルを紹介する書籍の一部をご紹介しました。
これまでに書いた記事は本としてまとめておりますので、ぜひ下記のリンクからお読みください。 (すべての情報は無料で公開されています)
皆様の新しい発見へのお手伝いができれば、幸いです。

Beyond LLM:世界モデルが切り拓くフィジカルAIの時代
https://zenn.dev/oggata/books/69bd97b5d0ede1

Discussion