视频生成模型深度解析:从 Video DiT 到 Sora 架构

6540 字
33 分钟
视频生成模型深度解析:从 Video DiT 到 Sora 架构

1. 视频生成的核心挑战#

1.1 为什么视频生成比图像生成更难?#

视频生成不仅仅是”生成多帧图像”——它要求模型在时间维度上保持一致性和连贯性:

图像生成 vs 视频生成:
图像生成:
输入: 文本描述
输出: 单张 512×512 图像
空间维度: H × W × C
计算量: O(H × W)
视频生成:
输入: 文本描述 (+ 可选首帧/姿态)
输出: T 帧视频,每帧 H × W
空间维度: T × H × W × C
时间维度: 连续的 T 帧必须保持:
→ 物体外观一致(同一角色每帧看起来相同)
→ 运动连贯(物体移动轨迹平滑)
→ 物理合理(重力、光照、遮挡符合物理规律)
→ 时序自然(动作、表情变化流畅)
计算量: O(T × H × W) — 通常是图像的 10-100 倍

1.2 视频生成的四类核心问题#

┌──────────────────────────────────────────────────────────────┐
│ 视频生成的四大挑战 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 1. 时序一致性 (Temporal Consistency) │
│ ───────────────────────────────────────────────────── │
│ 问题: 第 1 帧的狗和第 30 帧的狗要看起来是同一只狗 │
│ 原因: 扩散模型逐帧独立生成,缺乏全局身份追踪 │
│ 解法: 全视频序列联合建模(3D Attention / 视频 VAE) │
│ │
│ 2. 长程依赖 (Long-range Dependency) │
│ ───────────────────────────────────────────────────── │
│ 问题: 开场动作要影响结尾的响应 │
│ 原因: 帧间距离越大,相关性越弱 │
│ 解法: Transformer 的全局 Attention(比 RNN 更适合) │
│ │
│ 3. 计算可扩展性 (Computational Scalability) │
│ ───────────────────────────────────────────────────── │
│ 问题: 16 帧 1024×1024 = 1670 万像素 │
│ 原因: 直接在像素空间扩散计算量爆炸 │
│ 解法: 潜空间视频扩散 (Latent Video Diffusion) │
│ │
│ 4. 运动建模 (Motion Modeling) │
│ ───────────────────────────────────────────────────── │
│ 问题: 生成平滑、合理的运动轨迹 │
│ 原因: 运动是高度结构化的,难以从静态数据中学习 │
│ 解法: 光流监督 / 运动模块 / 物理先验 │
│ │
└──────────────────────────────────────────────────────────────┘

1.3 视频生成模型演进时间线#

2019: DDPM 提出 (Ho et al.) — 图像扩散基础奠定
2020: DDPM 扩展到视频 (Ho et al.) — 首个视频扩散
│ 缺点: 逐帧独立生成,时序一致性差
2022: LDM / Stable Diffusion — 潜空间扩散图像
│ 缺点: 只支持图像
2022: VideoLDM (Blattmann et al.) — 首个 Latent Video Diffusion
│ 引入视频 VAE,扩展 SD 到视频
2023: Make-A-Video (Singer et al., Meta) — 无需文本视频的预训练
│ 分离空间(图像扩散)+ 时间(插帧)
2023: Align Your Latents (Zhao et al.) — 高质量视频潜空间
2024: DiT (Peebles & Xie) — Transformer 替代 UNet
2024: Sora (OpenAI, Feb) — Video DiT,DiT 的视频扩展
│ 关键技术: 时空 patchify + 3D VAE + DiT 主干
2024: CogVideoX (Tsinghua) — 开源视频 DiT,3D 注意力
2024: Wan2.1 (ByteDance) — 开源视频 DiT,业界最佳
2024: Open-Sora (Vision SE) — 开源复现 Sora
2025: Sora 2.0 / Stable Video Diffusion 2 / HunyuanVideo

1.4 一句话概括视频扩散#

视频扩散模型的核心是在图像扩散的基础上引入时间维度——通过视频 VAE 把 T×H×W×3 的视频压缩到潜空间得到 T_c × H_c × W_c × C_z 的潜变量序列,然后在潜空间执行扩散去噪,最后用视频 VAE 解码器重建视频帧序列。Sora 的关键创新是把 DiT 的 2D patchify 扩展为 3D 时空 patchify,使 Transformer 能同时建模空间关系和时间关系。

2. 视频 VAE:潜空间时空压缩#

2.1 为什么需要视频 VAE?#

视频 VAE 把视频从像素空间压缩到潜空间,与图像 VAE 的逻辑相同但增加了时间维度:

class VideoVAE:
"""
视频 VAE: 压缩视频到低维潜空间。
继承自图像 VAE,增加了时间压缩维度。
"""
def __init__(self, spatial_downsample=8, temporal_downsample=4):
"""
参数:
spatial_downsample: 空间压缩比 (H → H/8)
temporal_downsample: 时间压缩比 (T → T/4)
"""
self.spatial_factor = spatial_downsample # 8
self.temporal_factor = temporal_downsample # 4
def encode(self, video):
"""
编码视频到潜空间。
参数:
video: (B, T, C, H, W) 原始视频
返回:
z: (B, T', C', H', W') 潜变量序列
"""
B, T, C, H, W = video.shape
# 空间压缩: H/8, W/8
# 时间压缩: T/4
# 通道扩展: C=3 → C'=16 或 16+16=32 (3D VAE)
z = self.encoder(video) # (B, T/4, 16, H/8, W/8)
return z
def decode(self, z):
"""
从潜空间解码到视频。
参数:
z: (B, T', C', H', W') 潜变量序列
返回:
video: (B, T, C, H, W) 重建视频
"""
return self.decoder(z)
def compress_ratio(self):
"""
压缩比计算。
以 16 帧 512×512 视频为例:
"""
T, H, W, C = 16, 512, 512, 3
# 像素数量
pixels = T * H * W * C # 16 × 512 × 512 × 3 = 12,582,912
# 潜空间大小
T_z = T // 4 # 4
H_z = H // 8 # 64
W_z = W // 8 # 64
C_z = 16 # 潜通道数
latent_pixels = T_z * H_z * W_z * C_z # 4 × 64 × 64 × 16 = 262,144
ratio = pixels / latent_pixels # ≈ 48 倍(与图像 LDM 相同)
return ratio

2.2 视频 VAE vs 图像 VAE#

def vae_comparison():
"""
视频 VAE vs 图像 VAE。
"""
return {
"维度": {
"图像 VAE": "3D (H, W, C)",
"视频 VAE": "5D (T, H, W, C)",
},
"编码器": {
"图像 VAE": "2D Conv (H, W)",
"视频 VAE": "3D Conv (T, H, W) — 同时压缩时空",
},
"时间压缩": {
"图像 VAE": "无",
"视频 VAE": "T/4 或 T/8 — 减少时序冗余",
},
"重建质量": {
"图像 VAE": "高(静态纹理)",
"视频 VAE": "中(时间闪烁是主要问题)",
},
"时序一致性": {
"图像 VAE": "无(逐帧编码)",
"视频 VAE": "高(联合编码)",
},
"代表模型": {
"图像 VAE": "SD 的 VAE (4 ch latent)",
"视频 VAE": "Sora 的 3D VAE, CogVideoX VAE, Wan VAE",
},
}

2.3 3D VAE 架构#

Sora 和主流视频 DiT 使用 3D VAE,同时在时间和空间维度上进行压缩:

class VideoVAE3D(nn.Module):
"""
3D 视频 VAE。
用于 Sora、CogVideoX、Wan2.1 等视频 DiT 模型。
"""
def __init__(self, in_channels=3, latent_channels=16):
super().__init__()
# ============ 3D 编码器 ============
self.encoder = nn.Sequential(
# 块 1: T×512×512 → T×256×256
nn.Conv3d(in_channels, 128, kernel_size=3, padding=1),
ResBlock3D(128, 128),
ResBlock3D(128, 128),
nn.Conv3d(128, 128, kernel_size=3, stride=(1, 2, 2), padding=1), # 只压缩空间
# 块 2: T×256×256 → T×128×128
nn.Conv3d(128, 256, kernel_size=3, padding=1),
ResBlock3D(256, 256),
ResBlock3D(256, 256),
nn.Conv3d(256, 256, kernel_size=3, stride=(1, 2, 2), padding=1),
# 块 3: T×128×128 → T×64×64
nn.Conv3d(256, 512, kernel_size=3, padding=1),
ResBlock3D(512, 512),
ResBlock3D(512, 512),
nn.Conv3d(512, 512, kernel_size=3, stride=(1, 2, 2), padding=1),
# 块 4: T×64×64 → T/2×64×64 (时间压缩开始)
nn.Conv3d(512, 512, kernel_size=3, stride=(2, 1, 1), padding=1),
# 最终投影到潜空间
nn.GroupNorm(32, 512),
nn.SiLU(),
nn.Conv3d(512, latent_channels, kernel_size=3, padding=1),
)
# ============ 量化/正则化 ============
# 视频 VAE 通常使用 VQ 或 EMA 量化(而非 KL)
self.quant_conv = nn.Conv3d(latent_channels, latent_channels, 1)
# ============ 3D 解码器 ============
self.decoder = nn.Sequential(
# 潜空间 → T/2×64×64
nn.Conv3d(latent_channels, 512, kernel_size=3, padding=1),
ResBlock3D(512, 512),
# 时间上采样: T/2×64×64 → T×64×64
nn.Conv3d(512, 512, kernel_size=4, stride=(2, 1, 1), padding=1),
# 空间上采样: T×64×64 → T×512×512
nn.Conv3d(512, 512, kernel_size=3, padding=1),
ResBlock3D(512, 512),
ResBlock3D(512, 512),
nn.ConvTranspose3d(512, 256, kernel_size=4, stride=(1, 2, 2), padding=1),
nn.Conv3d(256, 256, kernel_size=3, padding=1),
ResBlock3D(256, 256),
nn.ConvTranspose3d(256, 128, kernel_size=4, stride=(1, 2, 2), padding=1),
nn.Conv3d(128, 128, kernel_size=3, padding=1),
nn.Conv3d(128, in_channels, kernel_size=3, padding=1),
)
def encode(self, video):
"""
参数:
video: (B, C, T, H, W) — PyTorch 格式
返回:
z: (B, latent_channels, T', H', W')
"""
return self.encoder(video)
def decode(self, z):
return self.decoder(z)
class ResBlock3D(nn.Module):
"""3D 残差块。"""
def __init__(self, in_channels, out_channels):
super().__init__()
self.norm1 = nn.GroupNorm(32, in_channels)
self.conv1 = nn.Conv3d(in_channels, out_channels, 3, padding=1)
self.norm2 = nn.GroupNorm(32, out_channels)
self.conv2 = nn.Conv3d(out_channels, out_channels, 3, padding=1)
if in_channels != out_channels:
self.shortcut = nn.Conv3d(in_channels, out_channels, 1)
else:
self.shortcut = nn.Identity()
def forward(self, x):
h = F.silu(self.norm1(x))
h = self.conv1(h)
h = F.silu(self.norm2(h))
h = self.conv2(h)
return h + self.shortcut(x)

3. 时空 Patchify:Video DiT 的核心#

3.1 从 2D Patchify 到 3D Patchify#

DiT 的核心是把图像划分为 patches。视频 DiT 把这个思想扩展到时间维度:

DiT (2D 图像):
┌────────────────────────────────────┐
│ 图像: 512×512×3 │
│ ↓ Patchify (p=2, 空间) │
│ 每帧: (512/8)×(512/8) = 64×64 patches │
│ 每 patch: 2×2×3×C = 12C 维度 │
│ Patch 数量: 64×64 = 4096 │
└────────────────────────────────────┘
Video DiT (3D 视频):
┌────────────────────────────────────┐
│ 视频: T×512×512×3 │
│ ↓ Patchify (p_t=2, p_h=2, p_w=2)│
│ 时空: (T/4)×(512/8)×(512/8) │
│ = T_s × 64 × 64 patches │
│ 每 patch: 2×2×2×3×C = 24C 维度 │
│ Patch 数量: T_s × 64 × 64 │
│ (T_s = T/4, 时间压缩 4 倍) │
└────────────────────────────────────┘
关键: Video DiT 把 3D 时空立方体展平成序列
→ 输入: (T_s × 64 × 64) 个 tokens
→ 每个 token 维度: 2×2×2×3×C = 24C
→ 类似 DiT,通过线性投影到 D 维

3.2 时空 Patchify 的 PyTorch 实现#

class SpatioTemporalPatchify(nn.Module):
"""
时空 Patchify 层。
将视频 (B, C, T, H, W) 转为 tokens 序列 (B, N, D)。
"""
def __init__(self, patch_size_t=2, patch_size_h=2, patch_size_w=2,
in_channels=16, hidden_size=1024):
super().__init__()
self.pt = patch_size_t # 时间 patch 大小
self.ph = patch_size_h # 空间 patch 大小
self.pw = patch_size_w # 空间 patch 大小
self.in_channels = in_channels # VAE 潜通道数
# 每个 patch 展平后的维度
patch_dim = in_channels * pt * ph * pw # 16 × 2 × 2 × 2 = 128
# 线性投影到 Transformer 维度
self.proj = nn.Linear(patch_dim, hidden_size)
def forward(self, z):
"""
参数:
z: (B, C, T_s, H_s, W_s) 潜变量视频
例如: (B, 16, 4, 64, 64)
返回:
tokens: (B, N, D) Transformer 输入序列
其中 N = T_s/pt × H_s/ph × W_s/pw
"""
B, C, T, H, W = z.shape
# 1) 划分 patches
# z: (B, C, T, H, W) → (B, T/pt, C, pt, H/ph, W/pw, ph, pw)
z = z.view(
B,
T // self.pt, self.pt,
H // self.ph, self.ph,
W // self.pw, self.pw,
C,
)
# 转置: (B, T/pt, H/ph, W/pw, pt, ph, pw, C)
z = z.permute(0, 1, 3, 5, 2, 4, 6, 7).contiguous()
# 2) 展平每个 patch: (B, T_s, H_s, W_s, pt×ph×pw×C)
N_t = T // self.pt
N_h = H // self.ph
N_w = W // self.pw
z = z.view(B, N_t * N_h * N_w, self.pt * self.ph * self.pw * C)
# 3) 线性投影到 hidden_size
tokens = self.proj(z) # (B, N, D)
return tokens
class VideoDiT(nn.Module):
"""
视频 DiT。
"""
def __init__(self, hidden_size=1024, num_layers=16,
num_heads=16, patch_size_t=2, patch_size_h=2, patch_size_w=2,
in_channels=16):
super().__init__()
# Patchify
self.patchify = SpatioTemporalPatchify(
patch_size_t, patch_size_h, patch_size_w,
in_channels, hidden_size
)
# Patch Embedding (与 DiT 相同)
num_patches = self.patchify.num_patches
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches, hidden_size))
# Transformer
self.transformer = TransformerBlock(
hidden_size=hidden_size,
num_heads=num_heads,
mlp_ratio=4.0,
)
# 输出投影
self.proj_out = nn.Linear(hidden_size,
patch_size_t * patch_size_h * patch_size_w * in_channels)
# 时间步嵌入
self.time_embed = TimeEmbedding(hidden_size)
def forward(self, z, t, context):
"""
参数:
z: (B, C, T_s, H_s, W_s) 潜变量视频
t: (B,) 时间步
context: (B, seq_len, d) 文本 embedding
"""
# 1) Patchify
x = self.patchify(z) # (B, N, D)
# 2) 添加位置编码
x = x + self.pos_embed
# 3) 时间步嵌入
t_emb = self.time_embed(t)
# 4) Transformer 前向 (带 AdaLN-Zero)
for block in self.transformer.blocks:
x = block(x, t_emb, context)
# 5) 逆 Patchify
noise_pred = self.proj_out(x) # (B, N, patch_dim)
return noise_pred

4. Sora 架构深度解析#

4.1 Sora 的核心技术报告#

2024 年 2 月,OpenAI 发布 Sora 技术报告。虽然没有公布完整代码和权重,但其核心设计可以从报告中推断:

Sora 的三大核心组件:
┌──────────────────────────────────────────────────────────────┐
│ │
│ 1. Video SpatioTemporal Patchification │
│ ───────────────────────────────────────────────────── │
│ 将视频压缩为时空 patches │
│ • 空间: 16×16 pixel patches │
│ • 时间: 可变长度 (由视频时长决定) │
│ • 每个 patch → 潜向量 (通过视频 VAE) │
│ • 类比 DiT: 将 patch 视为 "visual sentence" │
│ │
│ 2. Video DiT (Diffusion Transformer) │
│ ───────────────────────────────────────────────────── │
│ 用 Transformer 处理时空 patches │
│ • 替代 UNet (之前的方法) │
│ • 更好的 scaling 特性 │
│ • Transformer 的全局 Attention │
│ • 基于 Diffusion (非自回归) │
│ │
│ 3. Versatile World Simulator (视频作为世界模型) │
│ ───────────────────────────────────────────────────── │
│ Sora 不仅是视频生成器 │
│ • 可以作为视频条件的视频编辑 │
│ • 可以做图像到视频 │
│ • 可以做视频扩展 (Video Inpainting) │
│ • 可以做视频到视频风格迁移 │
│ │
└──────────────────────────────────────────────────────────────┘

4.2 Sora 的视频生成能力#

def sora_capabilities():
"""
Sora 支持的视频生成任务。
"""
return {
"文生视频 (T2V)": {
"输入": "一段文本描述",
"输出": "最长 60 秒的连贯视频",
"示例": "prompt = 'A stylish woman walking...'"
},
"图生视频 (I2V)": {
"输入": "一张图像 + 文本描述",
"输出": "从图像开始延续的视频",
"示例": "用 DALL-E 3 生成的图像 → 视频"
},
"视频编辑": {
"输入": "现有视频 + 文本指令",
"输出": "符合指令的修改后视频",
"示例": "'让狗戴帽子' → 视频中狗戴帽子"
},
"视频扩展 (Inpainting/Outpainting)": {
"输入": "部分视频 + 新内容描述",
"输出": "扩展后的完整视频",
"示例": "给定开头 5 秒,生成后续 55 秒"
},
"视频到视频": {
"输入": "视频 + 风格描述",
"输出": "相同内容但不同风格",
"示例": "写实风格 → 动漫风格"
},
"动态封面": {
"输入": "静态图像",
"输出": "包含轻微运动的动态版本",
"示例": "DALL-E 图像 → 轻微动画"
},
"连接视频": {
"输入": "两个视频片段",
"输出": "在两片段间平滑过渡的视频",
"示例": "视频 A → 自然过渡 → 视频 B"
},
}

4.3 Sora 的技术限制#

def sora_limitations():
"""
Sora 的技术限制(来自 OpenAI 报告)。
"""
return {
"物理交互": {
"问题": "复杂物体交互的物理规律不准确",
"示例": "杯子倒下时水不一定符合重力",
"原因": "模型从视频数据中学习,缺乏物理先验",
},
"长程一致性": {
"问题": "视频越长,物体身份可能丢失",
"示例": "第 30 秒的人物外貌可能与第 1 秒不同",
"原因": "即使有 Transformer Attention,长序列仍困难",
},
"精确计数": {
"问题": "难以准确生成指定数量的事物",
"示例": "prompt '5 只狗' → 可能生成 4 或 6 只",
"原因": "视频中的数量信息不够精确",
},
"空间细节": {
"问题": "文字渲染和精细空间布局不准确",
"示例": "生成正确文本的招牌困难",
"原因": "视频空间分辨率有限",
},
"相机轨迹": {
"问题": "复杂相机运动可能不连贯",
"示例": "360 度旋转镜头可能中途变形",
"原因": "3D 一致性难以保证",
},
}

5. 开源视频 DiT 方案#

5.1 CogVideoX:清华团队#

CogVideoX 是最早的开源视频 DiT 之一(2024年7月):

def cogvideoX_architecture():
"""
CogVideoX 架构特点。
"""
return {
"团队": "Tsinghua & Zhipu AI",
"发布时间": "2024年7月",
"模型规模": "5B 参数 (DiT) + 600M (Text Encoder)",
"关键创新": "Expert Transformer (专家 Transformer)",
"注意力机制": {
"方法": "3D Full Attention",
"特点": "所有 tokens 之间的时空 Attention",
"问题": "O(N^2) 复杂度,N 是时空 tokens 数",
},
"文本编码器": "T5Encoder (来自 Google Flan-T5)",
"视频 VAE": "自研视频 VAE (4x 空间压缩,4x 时间压缩)",
"分辨率": "480×480, 16 帧",
"训练数据": "约 10M 文本-视频对",
"开源": "权重完全开源,推理代码开源",
}
def cogvideoX_transformer():
"""
CogVideoX 的 Transformer 结构。
"""
def forward(self, x, t, context, attention_mask=None):
# x: (B, N, D) — N = T_s × H_s × W_s
# 每个 Transformer Block:
# 1) Self-Attention (Q=K=V=x)
x = x + self.attn1(self.norm1(x), attention_mask=attention_mask)
# 2) Cross-Attention (Q=x, K=V=context)
x = x + self.attn2(self.norm2(x), context, attention_mask=attention_mask)
# 3) FFN
x = x + self.mlp(self.norm3(x))
return x

5.2 Wan2.1:字节跳动#

Wan2.1 是目前开源社区效果最好的视频 DiT:

def wan21_architecture():
"""
Wan2.1 架构特点。
"""
return {
"团队": "ByteDance (字节跳动)",
"发布时间": "2025年1月",
"模型规模": "14B 参数 (DiT) + 双文本编码器",
"关键创新": "Causal 3D Attention (因果 3D 注意力)",
"注意力机制": {
"方法": "Causal 3D Attention",
"特点": "时间维度因果 (只 attend 到之前和当前的帧)",
"空间维度": "全空间 Attention",
"优势": "比 Full Attention 更高效,适合长视频",
},
"文本编码器": "T5-XXL (1.8B) + CLIP ViT-L (300M)",
"视频 VAE": "自研 Wan VAE",
"分辨率": "480P / 720P / 1080P",
"帧数": "最长 5 分钟 (3000 帧 @ 10fps)",
"长视频生成": "通过自回归方式生成长视频",
"开源": "14B 模型完全开源 (HuggingFace)",
"显存需求": "FP16 需要 ~28GB (单卡 A100)",
}

5.3 Open-Sora:开源复现 Sora#

def opensora_architecture():
"""
Open-Sora 架构特点。
"""
return {
"团队": "Vision SE (社区主导)",
"发布时间": "2024年3月",
"目标": "开源复现 Sora 的完整流程",
"关键设计": "ST-DiT (Spatio-Temporal DiT)",
"注意力机制": {
"方法": "Causal 3D Attention",
"空间: 全 Attention",
"时间: Causal (只向前看)",
},
"视频 VAE": "支持多种 VAE (自研, CogVideoX, Wan)",
"特点": "完全开源,民主化视频生成技术",
"社区": "活跃的贡献者生态",
}

5.4 三大开源方案对比#

def opensource_comparison():
"""
CogVideoX vs Wan2.1 vs Open-Sora 对比。
"""
return {
"模型规模": {
"CogVideoX": "5B 参数",
"Wan2.1": "14B 参数",
"Open-Sora": "2B-9B (多个版本)",
},
"注意力机制": {
"CogVideoX": "3D Full Attention (全局)",
"Wan2.1": "Causal 3D Attention (时间因果)",
"Open-Sora": "Causal 3D Attention",
},
"分辨率": {
"CogVideoX": "480×480",
"Wan2.1": "480P - 1080P",
"Open-Sora": "16:9, 9:16, 1:1",
},
"帧数": {
"CogVideoX": "最多 32 帧",
"Wan2.1": "最长 5 分钟",
"Open-Sora": "最多 240 帧",
},
"视频质量": {
"CogVideoX": "★★★☆☆ (早期开源)",
"Wan2.1": "★★★★★ (最佳开源)",
"Open-Sora": "★★★★☆ (持续改进)",
},
"开源程度": {
"CogVideoX": "权重 + 代码完全开源",
"Wan2.1": "权重 + 代码完全开源",
"Open-Sora": "权重 + 代码完全开源",
},
}

6. Latent Video Diffusion(VideoLDM / LVDM)#

6.1 VideoLDM:首个 Latent Video Diffusion#

VideoLDM(Blattmann et al., 2022/2023)是首个把 Latent Diffusion 扩展到视频的工作:

VideoLDM 架构:
┌──────────────────────────────────────────────────────────────┐
│ │
│ 输入视频: T × 512 × 512 × 3 │
│ ↓ │
│ 视频 VAE (3D): T × 512 × 512 × 3 │
│ → T/4 × 64 × 64 × 4 (潜空间) │
│ ↓ │
│ 时间层 (Temporal Layers): │
│ 在潜空间添加时间建模层 (3D Conv / Temporal Attention) │
│ ↓ │
│ 空间层 (Spatial Layers): │
│ SD 的 UNet 保持不变 (处理每帧空间) │
│ ↓ │
│ 扩散过程: 在 T/4 × 64 × 64 潜空间执行 DDPM │
│ ↓ │
│ 视频 VAE 解码: 潜变量 → 视频 │
│ │
│ 关键设计: │
│ • 时间层插入 SD UNet 的 ResBlock 之间 │
│ • 时间层在潜空间的 T 维度上建模 │
│ • 冻结空间层(使用预训练 SD 权重) │
│ • 只训练时间层(高效微调) │
│ │
└──────────────────────────────────────────────────────────────┘

6.2 VideoLDM 时间层实现#

class TemporalLayer(nn.Module):
"""
VideoLDM 的时间层。
插入到 SD UNet 的 ResBlock 之间。
"""
def __init__(self, channels, num_frames):
super().__init__()
self.channels = channels
self.num_frames = num_frames
# 3D 卷积 (时间 + 空间)
# 作用: 在时间维度上建模帧间关系
self.temporal_conv = nn.Sequential(
nn.Conv3d(channels, channels, kernel_size=3, padding=1),
nn.GroupNorm(32, channels),
nn.SiLU(),
nn.Conv3d(channels, channels, kernel_size=3, padding=1),
)
# 残差连接
self.residual_scale = 0.1 # 小权重开始,避免破坏预训练
def forward(self, x):
"""
参数:
x: (B*T, C, H, W) — UNet 的特征
返回:
融合了时间信息的特征
"""
BT, C, H, W = x.shape
# 恢复时间维度: (B*T, C, H, W) → (B, C, T, H, W)
B = BT // self.num_frames
x = x.view(B, self.num_frames, C, H, W)
x = x.permute(0, 2, 1, 3, 4) # (B, C, T, H, W)
# 3D 卷积 (同时处理时间 + 空间)
h = self.temporal_conv(x)
# 残差连接
h = x + self.residual_scale * h
# 展平回: (B, C, T, H, W) → (B*T, C, H, W)
h = h.permute(0, 2, 1, 3, 4).reshape(BT, C, H, W)
return h
class VideoLDMUNet(nn.Module):
"""
带时间层的 VideoLDM UNet。
"""
def __init__(self, base_unet, num_frames=16):
super().__init__()
self.unet = base_unet
self.num_frames = num_frames
# 在每个 ResBlock 后插入时间层
self.temporal_layers = nn.ModuleList([
TemporalLayer(ch, num_frames)
for ch in base_unet.channel_list
])
def forward(self, x_t, t, context):
"""
参数:
x_t: (B*T, C, H, W) — 展平的时空潜变量
t: (B,) — 时间步(所有帧相同)
context: (B, seq_len, d) — 文本 embedding
"""
# 通过 UNet(处理空间信息)
h = self.unet.forward_spatial(x_t, t, context)
# 通过时间层(处理时间信息)
for temp_layer in self.temporal_layers:
h = temp_layer(h)
return h

6.3 LVDM:统一 Latent Video Diffusion#

LVDM(Latent Video Diffusion Models, 2022)在 VideoLDM 基础上进一步优化:

def lvdm_improvements():
"""
LVDM 相比 VideoLDM 的改进。
"""
return {
"长视频生成": {
"VideoLDM": "固定长度 (如 16 帧)",
"LVDM": "通过分层生成支持可变长度",
},
"时间建模": {
"VideoLDM": "3D Conv(局部时间)",
"LVDM": "Temporal Attention(全局时间)",
},
"训练效率": {
"VideoLDM": "需要逐帧编码",
"LVDM": "批量视频编码,更高效",
},
"无条件生成": {
"VideoLDM": "困难",
"LVDM": "通过分层设计改善",
},
}

7. 关键技术:3D 注意力与因果掩码#

7.1 3D 空间-时间注意力#

视频 DiT 中的注意力需要在时空三维空间中计算:

def attention_3d():
"""
3D 时空注意力的计算方式。
"""
def compute_full_3d_attention(tokens_3d, num_heads=16):
"""
全 3D 注意力(所有 tokens 互相关注)。
参数:
tokens_3d: (B, T, H, W, D) — 时空 tokens
返回:
输出: (B, T, H, W, D) — 更新后的 tokens
"""
B, T, H, W, D = tokens_3d.shape
N = T * H * W # tokens 总数
# 展平: (B, T, H, W, D) → (B, N, D)
x = tokens_3d.view(B, N, D)
# 分头
H_heads = num_heads
d_head = D // H_heads
# Q, K, V: (B, N, D)
Q = compute_Q(x) # (B, N, D)
K = compute_K(x)
V = compute_V(x)
# Reshape: (B, N, D) → (B, H, N, d_head)
Q = Q.view(B, N, H_heads, d_head).transpose(1, 2)
K = K.view(B, N, H_heads, d_head).transpose(1, 2)
V = V.view(B, N, H_heads, d_head).transpose(1, 2)
# 注意力: (B, H, N, N) — O(N^2) 复杂度
attn = (Q @ K.transpose(-2, -1)) / (d_head ** 0.5)
attn = F.softmax(attn, dim=-1)
# 输出: (B, H, N, d_head) → (B, N, D)
out = (attn @ V).transpose(1, 2).reshape(B, N, D)
return out.view(B, T, H, W, D)
def compute_causal_3d_attention(tokens_3d, num_heads=16):
"""
因果 3D 注意力(时间维度因果)。
参数:
tokens_3d: (B, T, H, W, D)
返回:
输出: (B, T, H, W, D)
"""
B, T, H, W, D = tokens_3d.shape
N = T * H * W
x = tokens_3d.view(B, N, D)
# Q, K, V (同上)
Q, K, V = compute_QKV(x)
# 掩码: 时间维度因果
# 帧 t 只能 attend 到帧 0, 1, ..., t
# 不能 attend 到帧 t+1, ..., T-1
mask = torch.zeros(T, T, device=tokens_3d.device)
for i in range(T):
for j in range(i + 1, T):
mask[i, j] = float("-inf")
# 扩展掩码到 (B, H, N, N)
mask_3d = mask.unsqueeze(0).unsqueeze(0) # (1, 1, T, T)
mask_3d = mask_3d.unsqueeze(-1).unsqueeze(-1) # (1, 1, T, T, 1, 1)
mask_3d = mask_3d.expand(B, H_heads, T, T, H * W, H * W)
# 应用掩码
attn = (Q @ K.transpose(-2, -1)) / (d_head ** 0.5)
attn = attn + mask_3d # 因果掩码
attn = F.softmax(attn, dim=-1)
return (attn @ V).view(B, T, H, W, D)
return {"full_3d": compute_full_3d_attention, "causal_3d": compute_causal_3d_attention}

7.2 注意力复杂度分析#

def attention_complexity():
"""
注意力机制的计算复杂度对比。
"""
return {
"2D Full Attention (DiT, 图像)": {
"图像尺寸": "512×512",
"Patch 数 (p=2, 压缩8x)": "64×64 = 4096",
"复杂度": "O(4096²) = 16.8M",
},
"3D Full Attention (视频)": {
"视频尺寸": "16×512×512",
"Patch 数": "4×64×64 = 16384",
"复杂度": "O(16384²) = 268M",
},
"3D Causal Attention": {
"视频尺寸": "16×512×512",
"有效计算": "每帧只 attend 到之前帧",
"复杂度": "O(T² × H² × W²) = 约 50M",
"节省": "约 5x",
},
"Sparse Attention (可选)": {
"方法": "空间局部 + 时间稀疏",
"复杂度": "O(T × H × W × k²)",
"k": "局部窗口大小 (如 7)",
},
}

8. 训练与推理#

8.1 视频 DiT 训练流程#

def train_video_dit(video_model, vae, text_encoder, dataloader,
optimizer, device, num_frames=16):
"""
视频 DiT 训练循环。
"""
def forward_batch(videos, prompts):
"""
参数:
videos: (B, T, C, H, W) 原始视频
prompts: list[str] 文本描述
"""
B, T, C, H, W = videos.shape
# ============ 1) 视频 VAE 编码 ============
with torch.no_grad():
# (B, T, C, H, W) → (B, C, T, H, W) (PyTorch 格式)
videos = videos.permute(0, 1, 2, 3, 4)
z = vae.encode(videos) # (B, C', T', H', W')
# ============ 2) 文本编码 ============
context = text_encoder.encode(prompts) # (B, seq_len, d)
# ============ 3) 加噪 ============
t = torch.randint(0, 1000, (B,), device=device)
noise = torch.randn_like(z)
alpha_bar = diffusion_schedule(t)
# 对所有帧加相同噪声(时序一致性关键)
alpha_bar = alpha_bar.view(B, 1, 1, 1, 1)
z_noisy = alpha_bar.sqrt() * z + (1 - alpha_bar).sqrt() * noise
# ============ 4) Patchify ============
noise_pred = video_model(z_noisy, t, context)
# ============ 5) 损失 ============
loss = F.mse_loss(noise_pred, noise)
return loss
# 训练循环
video_model.train()
for batch in tqdm(dataloader):
videos, prompts = batch["video"].to(device), batch["prompt"]
loss = forward_batch(videos, prompts)
optimizer.zero_grad()
loss.backward()
optimizer.step()
return loss.item()

8.2 视频 DiT 推理流程#

@torch.no_grad()
def generate_video(video_model, vae, text_encoder,
prompt, num_frames=16, num_steps=50,
height=512, width=512, guidance_scale=7.5):
"""
视频 DiT 推理。
参数:
prompt: str 文本描述
num_frames: int 生成帧数
num_steps: int DDPM 步数
guidance_scale: float CFG 强度
"""
# 1) 文本编码
text_emb = text_encoder.encode([prompt])
uncond_emb = text_encoder.encode([""])
# 2) 初始化潜空间噪声
T_s = num_frames // 4 # 时间压缩后的帧数
H_s = height // 8 # 空间压缩后的高度
W_s = width // 8 # 空间压缩后的宽度
latent_shape = (1, 16, T_s, H_s, W_s) # (B, C', T', H', W')
z_T = torch.randn(latent_shape, device=device)
# 3) DDIM 采样
timesteps = torch.linspace(999, 0, num_steps, device=device).long()
for i, t in enumerate(tqdm(timesteps)):
t_tensor = torch.tensor([t], device=device).expand(1)
# 条件预测
noise_pred_cond = video_model(z_T, t_tensor, text_emb)
# 无条件预测 (CFG)
noise_pred_uncond = video_model(z_T, t_tensor, uncond_emb)
# CFG 合并
noise_pred = noise_pred_uncond + \
guidance_scale * (noise_pred_cond - noise_pred_uncond)
# DDIM 去噪步
z_T = ddim_step(z_T, noise_pred, t, timesteps[i - 1] if i > 0 else 0)
# 4) VAE 解码
video = vae.decode(z_T) # (1, C, T', H', W')
# 5) 后处理
video = video.permute(0, 2, 1, 3, 4) # → (1, T, C, H, W)
video = video.cpu().numpy()
return video

9. 技术组合与应用#

9.1 视频生成 + 控制 (Video ControlNet)#

def video_controlnet():
"""
视频条件控制。
将 ControlNet 扩展到视频领域。
"""
return {
"任务": "用姿态/深度/光流控制视频生成",
"方法": "在 Video DiT 中加入条件编码器",
"条件类型": {
"姿态": "OpenPose 骨骼控制角色动作",
"深度": "Depth Map 控制空间结构",
"光流": "Optical Flow 控制运动轨迹",
"边缘": "Edge Map 控制物体轮廓",
},
"关键问题": {
"时序一致性": "条件也需要在时间上保持一致",
"长视频": "长序列条件注入困难",
},
"代表工作": "ControlVideo (2023), VideoControlNet (2024)",
}

9.2 视频生成 + LoRA#

def video_lora():
"""
视频 LoRA。
用 LoRA 高效微调视频模型。
"""
return {
"任务": "训练特定风格/角色的视频 LoRA",
"方法": "在 Video DiT 中应用 LoRA",
"目标层": {
"DiT": "Q, K, V 投影 + FFN",
"VAE": "通常不训练",
"Text Encoder": "可选 (Q, K, V)",
},
"挑战": {
"显存": "视频模型更大,LoRA 参数量也更大",
"数据": "高质量视频数据稀缺",
"时序": "LoRA 需要保持时序一致性",
},
}

10. 总结#

10.1 核心要点#

维度关键要点
核心架构Video DiT = DiT 的时空扩展(3D patchify + 3D VAE)
视频 VAE3D Conv 同时压缩时空 (T/4 × H/8 × W/8)
时空 Patchify每个 patch = p_t × p_h × p_w × C_in
注意力机制3D Full Attention(全局)vs Causal 3D(高效)
Sora 贡献时空 patchify + DiT 主干 + 多任务视频生成
开源方案CogVideoX(5B)/ Wan2.1(14B,业界最佳)/ Open-Sora
VideoLDM在 SD UNet 中插入时间层,微调效率高
计算瓶颈Attention O(N²) 是最大挑战,需要稀疏/Causal 优化

10.2 技术演进路线#

图像扩散 (DDPM, 2020):
像素空间 → O(512²) 计算量
图像潜扩散 (LDM, 2022):
潜空间 48x 压缩 → O(64²) 计算量
VideoLDM (2022-23):
+ 时间层 (Temporal Layer) → 时序一致性
Video DiT / Sora (2024):
+ Transformer 替代 UNet → 更好的 scaling
+ 3D Patchify → 统一时空建模
当前 (2025-26):
长视频生成 (Wan2.1 5 分钟)
高分辨率 (1080P)
开源生态 (CogVideoX, Wan2.1, Open-Sora)
多模态控制 (Video ControlNet)

10.3 一句话总结#

视频生成扩散模型的核心挑战是在时间维度上保持一致性——Video VAE 把视频压缩到潜空间,Video DiT 用 3D patchify 把时空信息展平为 token 序列,通过 Transformer 的全局 Attention 联合建模空间和时间关系,Sora 的技术报告则揭示了这一范式的巨大潜力:仅凭扩散 Transformer + 时空 patchify + 大规模训练,就能生成最长 60 秒的物理合理视频,引发了 2024 年的视频生成热潮,也催生了 CogVideoX、Wan2.1、Open-Sora 等开源替代方案的快速跟进。

10.4 推荐资源#

论文:
- Sora (OpenAI, 2024): "Video Generation Models as World Simulators" (技术报告)
- VideoLDM (Blattmann et al., 2023): "Align Your Latents: High-Resolution Video Synthesis"
- CogVideoX (Zhao et al., 2024): "CogVideoX: Large-Scale Open-Source Video Diffusion Transformer"
- Wan2.1 (ByteDance, 2025): 14B 开源视频 DiT
代码:
- THUDM/CogVideoX: https://github.com/THUDM/CogVideoX
- Wan-AI/Wan2.1: https://github.com/Wan-AI/Wan2.1
- hpcaitech/Open-Sora: https://github.com/hpcaitech/Open-Sora
模型:
- HuggingFace: THUDM/CogVideoX-5B
- HuggingFace: Wan-AI/Wan2.1-I2V-14B
相关:
- Make-A-Video (Meta, 2023): 无文本视频的预训练视频扩散
- LVDM (2022): Latent Video Diffusion Models
- I2V (Image-to-Video): Pika, Runway Gen-2, Gen-3

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

视频生成模型深度解析:从 Video DiT 到 Sora 架构
https://aiattnstudio.link/posts/video-generation-models/
作者
Federico
发布于
2026-07-16
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author

Federico

AI Research Lab

Hello, I'm Federico.

关于实验室 / About
公告

欢迎来到Federico的个人博客

分类
标签
站点统计
57文章
7分类
404标签