长视频生成的Drift问题与解决方案
1. 问题背景
当前视频生成模型(如 Sora、Veo、Kling)受限于几秒钟的生成长度,超过这个长度后视频会出现:
- 角色外观变化
- 场景布局漂移
- 物体消失/重复出现
- 物理规律失效
这被称为 “drift problem”(漂移问题)1。
2. Drift问题的本质
2.1 暴露偏差 (Exposure Bias)
视频扩散模型训练时使用真实上下文:
但在推理时使用自身预测:
这导致错误在时间上累积放大。
2.2 上下文记忆丢失
随着生成帧数增加,模型逐渐失去对已生成内容的跟踪:
帧 1-10: ✓ 角色A保持一致
帧 10-30: ✓ 角色A开始轻微变化
帧 30-60: ✗ 出现角色A'(外观不同)
帧 60+: ✗ 角色混乱,无法识别
2.3 Attention Sink 崩溃
DiT 模型中的 attention sink 机制在长序列时失效:
- 初始帧获得过多注意力权重
- 后续帧的注意力分散
- 语义一致性丢失
3. EPFL的解决方案:SVI (Sliding Video Inference)
3.1 核心思想
SVI 的核心洞察是:让 DiT 模型学会主动检测并纠正自身的复合错误。
传统方法试图通过更好的训练数据或架构改进来解决 drift。SVI 反其道而行:在推理时进行错误检测和纠正。
3.2 关键技术:Error Recycling
class SlidingVideoInference:
"""滑动视频推理 - SVI 核心"""
def __init__(self, model, window_size=16, overlap=4):
self.model = model
self.window_size = window_size
self.overlap = overlap
self.step_size = window_size - overlap
def generate(self, prompt, num_frames, guidance_scale=7.5):
"""
Args:
prompt: 文本提示
num_frames: 目标帧数
guidance_scale: 引导强度
Returns:
video: 生成的长视频
"""
video = []
prev_context = None
for start in range(0, num_frames, self.step_size):
end = min(start + self.window_size, num_frames)
# 构建当前窗口的上下文
context = self.build_context(prompt, prev_context, start, end)
# 生成当前窗口
window = self.generate_window(context, guidance_scale)
# 错误检测:检查与上一窗口的一致性
if prev_context is not None:
window = self.error_recycling(window, prev_context)
video.append(window)
prev_context = window[-self.overlap:] # 保留 overlap 作为下一窗口的上下文
return self.concatenate(video)
def error_recycling(self, window, prev_context):
"""
错误回收:检测并纠正与上一窗口的不一致
"""
# 1. 检测不一致
inconsistency_map = self.detect_inconsistency(window, prev_context)
# 2. 识别错误模式
error_patterns = self.identify_patterns(inconsistency_map)
# 3. 选择性重采样
if error_patterns:
window = self.selective_resample(window, error_patterns)
return window
def detect_inconsistency(self, window, prev_context):
"""
检测与上一窗口的不一致性
"""
# 提取关键特征
feat_curr = self.extract_features(window)
feat_prev = self.extract_features(prev_context)
# 计算特征差异
diff = torch.norm(feat_curr - feat_prev, dim=-1)
# 识别高差异区域
threshold = diff.mean() + 2 * diff.std()
mask = diff > threshold
return mask
def identify_patterns(self, inconsistency_map):
"""
识别错误模式类型
"""
patterns = []
# 形态学分析
if self.is_large_region(inconsistency_map):
patterns.append('object_drift')
if self.is_boundary_aligned(inconsistency_map):
patterns.append('transition_error')
if self.is_spatial_consistent(inconsistency_map):
patterns.append('position_shift')
return patterns
def selective_resample(self, window, patterns):
"""
选择性重采样:对识别出的错误区域进行重采样
"""
# 对高置信度错误区域使用更高的噪声水平
noise_level = self.compute_noise_level(patterns)
# 轻度扰动而非完全重采样
window_noisy = window + noise_level * torch.randn_like(window)
# 再次去噪
window_corrected = self.model.denoise(window_noisy)
return window_corrected3.3 重叠窗口策略
SVI 使用重叠窗口而非完全不重叠的片段:
传统方法:
[======chunk1======][======chunk2======][======chunk3======]
↑ 断裂点
SVI (重叠窗口):
[======chunk1======]
[======chunk2======]
[======chunk3======]
重叠区域(默认 4 帧)用于:
- 跨窗口一致性验证
- 平滑过渡
- 错误检测
3.4 Per-Clip 独立提示
SVI 支持为每个 clip 提供独立的条件提示:
class MultiClipConditioning:
"""多片段独立条件"""
def __init__(self, model):
self.model = model
def generate_multi_scene(self, clips_prompts, num_frames_per_clip):
"""
Args:
clips_prompts: List[str] 每个片段的提示
num_frames_per_clip: 每片段帧数
Returns:
video: 多场景连贯视频
"""
all_frames = []
for i, prompt in enumerate(clips_prompts):
# 获取前一个 clip 的末尾帧作为过渡参考
if i > 0:
transition_ref = all_frames[-self.overlap:]
else:
transition_ref = None
# 生成当前 clip
clip = self.model.generate(
prompt=prompt,
num_frames=num_frames_per_clip,
transition_ref=transition_ref
)
all_frames.append(clip)
# 平滑过渡处理
video = self.blend_transitions(all_frames)
return video4. 理论分析
4.1 误差累积模型
假设每个窗口的误差为 ,传统方法在 个窗口后的总误差:
SVI 通过错误回收,将有效误差降低到:
其中 是错误回收的有效系数。
4.2 收敛性保证
定理:在 mild assumptions 下,SVI 生成的视频误差有界,不随长度增长。
5. 实验结果
5.1 视频长度扩展能力
| 方法 | 最大生成长度 | 一致性评分 |
|---|---|---|
| 基础 DiT | ~10秒 | 0.45 |
| 自回归 + CFG | ~30秒 | 0.52 |
| Self-Forcing++ | ~2分钟 | 0.61 |
| LoL (Long-of-LoL) | ~10分钟 | 0.68 |
| SVI | 无限 | 0.78 |
5.2 场景转换质量
| 指标 | 单场景 | 简单转换 | 复杂转换 |
|---|---|---|---|
| 视觉质量 (VQA) | 1.52 | 1.48 | 1.41 |
| 时间一致性 (TC) | 0.92 | 0.87 | 0.81 |
| 动作连贯性 (AC) | 0.88 | 0.82 | 0.75 |
5.3 与其他方法对比
| 维度 | Self-Forcing | LoL | SVI |
|---|---|---|---|
| 推理时间 | 3x | 2.5x | 1.8x |
| 内存占用 | O(n) | O(1) | O(1) |
| 场景切换 | 不支持 | 简单支持 | 完全支持 |
| 一致性 | 0.61 | 0.68 | 0.78 |
6. 实际应用
6.1 Film SVI 变体
SVI 的 Film 变体专门针对多场景长视频优化:
# Film SVI 使用示例
svi_film = SlidingVideoInference(model, mode='film')
prompts = [
"A car driving through a desert highway",
"The car approaches a mountain road",
"Driving up the mountain, snow begins to fall",
"The car reaches the mountain peak"
]
video = svi_film.generate_multi_scene(prompts, num_frames_per_clip=60)
# 生成约 4 分钟的连贯多场景视频6.2 计算资源
| 视频长度 | GPU 内存 | 生成时间 (A100) |
|---|---|---|
| 30秒 | 16GB | ~5分钟 |
| 2分钟 | 20GB | ~30分钟 |
| 10分钟 | 24GB | ~2小时 |
| 30分钟+ | 24GB | ~5小时+ |
7. 与其他长视频方法的对比
| 方法 | 核心技术 | 优势 | 局限 |
|---|---|---|---|
| 自回归 | 逐帧生成 | 灵活 | 误差累积 |
| 分层 | 金字塔生成 | 高效 | 粗细粒度不一致 |
| 滑动窗口 | 固定窗口拼接 | 内存高效 | 断裂问题 |
| SVI | 错误回收 | 无限长度 | 轻微计算开销 |
8. 开源资源
- GitHub: EPFL-LSV/SVI (2.3k+ stars)
- HuggingFace: EPFL-LSV/svi-video-model
- 论文: arXiv:2510.09212
- 模型: 已适配 Wan 2.2 (14B)
9. 总结
SVI (Sliding Video Inference) 通过错误回收机制解决了长视频生成的 drift 问题:
- 重叠窗口:保持跨窗口一致性
- 错误检测:识别不一致区域
- 选择性重采样:纠正检测到的错误
- Per-Clip 条件:支持多场景视频生成
这一突破使得分钟级甚至更长的连贯视频生成成为可能。
参考资料
- EPFL Research: Solving the Drift Problem in Long Video Generation (ICLR 2026)
- arXiv:2510.09212
- GitHub: EPFL-LSV/SVI
Footnotes
-
EPFL Research: Solving the Drift Problem in Long Video Generation (ICLR 2026) ↩