ShotStream: Streaming Multi-Shot Video Generation for Interactive Storytelling

Paper: arXiv:2603.25746 Code: KlingAIResearch/ShotStream Code reference: main @ 7ddcfaef (2026-03-31)

一句话定位:ShotStream 把多镜头长视频从“一次性离线生成整段故事”改写成“按镜头在线续写”,用双缓存维持跨镜头与镜头内一致性,再用两阶段 self-forcing + DMD 把约 50 步的双向 teacher 蒸馏成 4 步 causal student,从而在单张 H200 上达到约 15.95/16 FPS 的交互式多镜头生成。

1. Motivation (研究动机)

1.1 多镜头叙事不是普通长视频外推

论文关注的是 multi-shot video generation,而不是单一场景的无限延长。 真实叙事需要镜头切换、角色视角变化、空间关系变化和局部事件推进。 一个长镜头模型即使能生成数百帧,也可能只是在同一状态附近漂移。 多镜头任务要求模型理解“上一镜头发生了什么”和“下一镜头要改变什么”。 这类任务的输入通常含有 global caption 和多个 shot-level caption。 global caption 描述故事弧、角色、整体风格。 shot-level caption 描述当前镜头的动作、构图或局部事件。 如果只看目标镜头 caption,模型容易忘掉历史人物或背景。 如果把所有历史帧都塞进条件,又会超出视频 DiT 的上下文预算。 因此,ShotStream 的第一层动机是:如何在有限条件预算下保留足够历史。

100%

teaser 展示了连续多镜头输出,而不是只展示单镜头质量。 这些例子强调跨镜头主体、服装、风格和场景线索的一致性。 例如同一角色在近景、远景和切换镜头中需要保持身份。 这比简单的 text-to-video prompt adherence 更难。 prompt adherence 只要求当前镜头符合文字。 narrative consistency 要求当前镜头还不能破坏前文。 ShotStream 的任务定义自然服务于 interactive storytelling。 用户可以先看已经生成的镜头,再决定下一镜头的文本指令。 这使系统更像“在线导演”而不是“离线批量渲染器”。

1.2 双向多镜头模型质量强但交互性弱

论文把现有强多镜头方法概括为 bidirectional multi-shot models。 这类模型通常在整段视频或多个片段上做联合建模。 由于能看到更完整的上下文,它们容易获得较好的局部画质。 但它们有两个交互式场景下的硬伤。 第一,推理延迟高,不能在用户追加新镜头指令后快速响应。 第二,生成过程离线化,用户很难在故事中途改变方向。 论文中 teacher 需要约 50 denoising steps。 对实时应用而言,50 步扩散推理会使等待时间过长。 这也解释了为什么论文要先训练 teacher,再蒸馏成 causal student。 teacher 负责提供质量上界和 next-shot 分布。 student 负责把这个分布压缩到可流式调用的低步数模型。

1.3 自回归长视频模型快但容易累积错误

另一类相关方法是 autoregressive / causal long-video generation。 它们按帧、chunk 或片段逐步生成,因此天然支持在线扩展。 但这类方法的核心问题是 exposure bias。 训练时模型常看 ground-truth history。 推理时模型只能看自己生成过的历史。 一旦前面镜头略微偏色、错人或错误构图,后续镜头会沿着错误历史继续滚动。 论文把这个问题称为 error accumulation。 multi-shot 场景下错误更显著,因为 shot boundary 本身就是分布突变点。 如果模型无法区分“历史镜头条件”和“当前镜头局部缓存”,就会把两个不同语义的上下文混在一起。 这会造成镜头边界处身份、背景或风格的漂移。 ShotStream 的 dual-cache 和 RoPE discontinuity 正是为这个边界问题设计的。

1.4 论文想同时满足四个属性

100%

论文把目标能力拆成 Multi-Shot、Long Gen.、Interactive、Real-Time。 传统 bidirectional multi-shot models 具备多镜头能力,但缺少长程、交互与实时。 autoregressive long video models 支持长视频和实时生成,但多镜头叙事控制不足。 ShotStream 的目标是同时保留四项能力。 这个目标决定了它不能只做 prompt engineering。 它必须改变建模形式:从 full-sequence generation 改成 next-shot generation。 它也不能只做普通蒸馏:必须让蒸馏时的上下文分布接近真实推理。 这就是 two-stage self-forcing 的作用。 论文的贡献不是提出一个孤立模块,而是一条完整路径。 路径是:bidirectional next-shot teacher → causal 4-step student → dual-cache memory → staged self-forcing rollout。

2. Idea (核心思想)

2.1 任务重写:把故事看成 next-shot streaming

ShotStream 将多镜头视频写成镜头序列 。 每个镜头有自己的 shot caption。 整个故事还有一个 global caption。 生成第 个镜头时,模型不再重新生成整个序列。 它只需要根据历史镜头 和当前文字生成 。 用户在第 个镜头开始前可以修改下一段叙事。 这就是 streaming prompts 的含义。 该重写让系统天然支持 on-the-fly synthesis。 它也使历史条件压缩成为核心问题。 历史不能无限增长,因此需要选择代表性 context frames。 论文采用 dynamic sampling strategy,而不是固定取第一帧或首尾帧。 若已有 个历史镜头且条件预算为 ,每个历史镜头先分得 帧。 剩余预算分配给最近的镜头。 论文实验中 。 直觉是最近镜头通常对下一镜头最关键,因此吃掉余量更合理。

2.2 先学强 teacher,再蒸馏快 student

100%

第一阶段训练 bidirectional next-shot teacher。teacher 基于 Wan2.1-T2V-1.3B。teacher 的输入包含稀疏历史条件帧和当前目标镜头噪声 latent。历史条件帧经过 3D VAE 编码为 。目标镜头噪声 latent 写作 。论文给出的条件编码为:。条件 latent 和目标 noisy latent 分别 patchify 后沿 frame 维拼接。公式是 x_j = \text{Patchify}(z_j), z_j \in \{z_{context}, z_t}\}

输入 token 为 。噪声只加到目标镜头 token 上,context tokens 保持 clean。这样 DiT 原生 3D self-attention 可以直接建模 condition 与 target 的交互。teacher 质量较高,但推理慢。第二阶段把 teacher 蒸馏为 causal student。student 使用 DMD,把多步 teacher 的分布压缩到 few-step 生成器。论文明确说 student 是 4-step causal model。这个设计把“质量学习”和“低延迟执行”分离。

2.3 双缓存:历史一致性和当前镜头连续性分开处理

100%

causal student 的关键不是只有一个 KV cache。 它有两个语义不同的缓存。 global context cache 存历史镜头中抽样的条件帧。 它负责 inter-shot consistency。 local context cache 存当前镜头内部已经生成的 chunks。 它负责 intra-shot continuity。 如果把两个 cache 直接拼在一起,模型会不知道哪些 token 是过去镜头、哪些 token 是当前镜头。 ShotStream 用 RoPE discontinuity indicator 显式制造镜头边界差异。 对第 个 shot 内第 个 latent,时间旋转角写作 是基础 temporal frequency。 是 shot-boundary phase shift。 这个相位跳变相当于给不同镜头增加离散边界标记。 它不需要新增大量可训练参数。 与 learnable embedding 相比,论文 ablation 显示 RoPE offset 在跨镜头一致性上更强。

2.4 两阶段 self-forcing:逐步缩小训练-推理差距

Stage 1 是 intra-shot self-forcing。 这一阶段仍使用 ground-truth historical shots 作为 global context。 但当前镜头内部是 causal chunk-by-chunk rollout。 local cache 使用当前镜头中模型自己生成的 chunks,而不是 ground truth chunks。 这一步解决镜头内 causal 生成能力。 Stage 2 是 inter-shot self-forcing。 这一阶段让模型用自己先前生成的镜头作为历史。 每到一个 shot boundary,就用生成内容更新 global context cache,并重置 local cache。 DMD loss 只作用于当前新生成的 shot。 这一阶段更接近真实推理。 它让模型学会在自己产生的历史上恢复和继续叙事。 因此 Stage 1 和 Stage 2 不是重复训练。 Stage 1 建立 next-shot causal 基础。 Stage 2 对齐 inference-time rollout 分布。

3. Method (方法)

3.1 符号与输入组织

每个样本由一个全局故事描述和多个镜头描述构成。 全局描述对应代码中的 global_captions。 镜头级描述对应代码中的 shots_captions。 镜头边界对应代码中的 shot_flag。 目标是按镜头生成输出帧,而不是一次生成全片。 每个历史镜头只抽若干 context frames。 这些 context frames 与目标镜头 noisy latent 拼接后送入 DiT。 对于 teacher,历史条件帧是从真实训练视频抽取。 对于 causal inference,历史条件帧来自已经生成的镜头。 这就是训练和推理差距的来源之一。 ShotStream 的方法部分围绕两个轴展开。 轴一是空间/时间 token 如何注入历史条件。 轴二是 causal student 如何在自己生成的历史上保持稳定。

3.2 Bidirectional next-shot teacher

teacher 的目标是建模 。它不是直接训练一个无限长视频模型。它只训练“给定历史,生成下一镜头”的能力。历史帧采样使用动态分配。当历史镜头数增加时,每个镜头分到的条件帧数下降。余量给最近镜头,避免最近上下文被低估。论文实验中最大条件帧预算是 6。released config tools/train/config/1_basemodel.yaml 也设置 max_context_frames: 6。teacher 同时注入 global caption 和对应 shot caption。这称为 multi-captions。

这么做的原因是历史帧本身没有文本标签时,模型难以判断哪个视觉元素对应哪个前文事件。论文 ablation 中 Target Caption 明显弱于 Multi-Captions。Target Caption 的 inter-shot semantic 是 0.681。Multi-Captions 的 inter-shot semantic 是 0.762。Target Caption 的 text alignment 是 0.194。Multi-Captions 的 text alignment 是 0.234。这说明历史文本不是可有可无的装饰。它帮助模型把历史视觉信息和语义描述绑定起来。

3.2.1 Teacher 的 frame concatenation

条件帧 经 VAE 编码为 。 目标镜头噪声 latent 写作 。 二者分别 patchify。 拼接发生在 frame dimension。 这与 channel concatenation 不同。 channel concat 把条件当成额外通道,依赖网络学习跨通道对应关系。 frame concat 让条件帧和目标帧共享时间维上的 self-attention。 因此 3D self-attention 可以直接比较历史帧和目标帧。 论文 ablation 中 Channel Concat 的 transition control 是 0.912。 Frame Concat 的 transition control 是 0.978。 Channel Concat 的 aesthetic quality 是 0.509。 Frame Concat 的 aesthetic quality 是 0.571。 这说明条件注入位置会影响镜头切换控制和视觉质量。

3.2.2 Teacher 的可训练参数选择

论文补充材料说 teacher 只优化 DiT block 中的 3D self-attention layers。 训练使用 Adam。 学习率为 。 batch size 为 64。 论文写训练 10,000 steps。 released config 1_basemodel.yamlonly_train3d: True 与论文一致。 released config 中 lr: 1.0e-05 与论文一致。 released config 中 total_batch_size: 64 与论文一致。 released config 中 max_iters: 30000 与论文补充材料的 10,000 steps 不一致。 因此复现实验时应把论文数值和 release config 区分开。 我在这篇笔记中把论文结果解释依赖论文补充材料。 代码映射仅说明公开 repo 当前配置,而不把 max_iters: 30000 当作论文最终训练步数。

3.3 Distribution Matching Distillation 到 4-step causal student

DMD 的目的不是简单监督 student 复刻 teacher 的单次输出。 它在分布层面让 student output distribution 接近 teacher/data distribution。 补充材料写成 reverse KL 目标。 对随机 timestep ,DMD 梯度近似为 data score 与 generator score 的差。 论文公式可概括为: 是 student generator。 是在真实/teacher 分布上训练的 score。 是在 student 输出分布上训练的 fake score。 表示 forward diffusion process。公开代码中相关实现集中在 model/dmd_frameconcat.pyDMDFrameConcat._compute_kl_grad 计算 real/fake score 差。DMDFrameConcat.compute_distribution_matching_loss 把梯度目标转成 MSE 形式的可反传 loss。

DMDFrameConcat.generator_loss 接收 context_latentshot_flags_for_rope,因此它不是普通单视频 DMD。released config 3_dmd.yaml / 4_dmd_long.yaml 设置 distribution_loss: dmd_frameconcat。两个 config 都使用 denoising_loss_type: flow。两个 config 的 denoising_step_list[1000, 740, 500, 260]。这与论文的 4-step causal student 对齐。

3.4 Dual-cache memory mechanism

双缓存的核心是把“跨镜头历史”和“当前镜头局部进度”分离。global context cache 只保存稀疏历史条件帧。local context cache 保存当前镜头已经生成的 chunks。在推理时,每生成一个新镜头,global context 会从所有已生成历史中重新采样。在当前镜头内部,每个 chunk 生成后进入 local cache。当进入下一个 shot boundary 时,local cache 应重置。这避免前一镜头的局部运动状态污染下一镜头。论文的 chunk size 是 3 latent frames。论文的 global cache 是 2 chunks。论文的 local cache 是 7 chunks。

released config 中 num_frame_per_block: 3 与 chunk size 一致。inference code pipeline/causal_inference_ar.py 中每个 shot 生成 noise = torch.randn([1, 21, ...])。21 latent frames 可理解为 7 个 block,每个 block 3 latent frames。这与 local cache 7 chunks 的描述一致。pipeline/causal_inference_ar.py_initialize_kv_cache 维护 local KV cache。

同一文件的 _initialize_context_kv_cache 维护 context KV cache。_set_all_modules_max_attention_size 会把 local attention size 转成 token 级窗口。这些代码说明论文中的 dual-cache 在 repo 中不是纯概念,而是落在实际 KV cache 初始化和 attention 窗口上。

3.4.1 RoPE discontinuity indicator

naive dual-cache 的问题是 token 序列没有明确告诉模型哪些 token 属于哪个镜头。 如果所有 token 沿同一连续时间轴编码,历史镜头和当前镜头会被误解为连续帧。 这不符合多镜头剪辑语义。 ShotStream 用 shot index 产生 RoPE 相位偏移。 论文写作 是镜头编号。 是镜头边界引入的相位 shift。 公开推理代码中有 shot_flags_for_rope。 在生成第一个镜头时,条件索引和 RoPE flags 置零。 后续镜头会根据历史 shot flags 填入对应边界信息。 当前目标镜头的噪声 latent 会追加一个新的 shot flag。 这与论文所说的 discontinuous RoPE 对应。 论文 ablation 中 w/o Indicator 的 inter-shot subject 是 0.507。 RoPE Offset 的 inter-shot subject 是 0.654。 w/o Indicator 的 inter-shot background 是 0.465。 RoPE Offset 的 inter-shot background 是 0.645。 因此 indicator 的最大收益不是单镜头画质,而是跨镜头身份和背景保持。

3.5 Two-stage self-forcing distillation

Stage 1: intra-shot self-forcing。输入历史仍来自 ground-truth historical shots。目标镜头按 chunk 自回归生成。local cache 使用当前模型已生成 chunks。该阶段主要学习“给定干净历史,如何 causal 地生成当前镜头”。补充材料说 Stage 1 大约 500 steps 收敛。Stage 1 batch size 为 32。generator 学习率是 。critic 学习率是 。generator:critic update ratio 为 1:5。released config 3_dmd.yamllr: 2.0e-06

released config 3_dmd.yamllr_critic: 4.0e-07。released config 3_dmd.yamldfake_gen_update_ratio: 6,与论文文字的 1:5 表述存在实现口径差异,需要以实际训练脚本为准。Stage 2: inter-shot self-forcing。输入历史改为 self-generated shots。每次迭代生成一个 5-second shot。到 shot boundary 后,用生成内容更新 global context cache。同时 reset local cache。Stage 2 使用 5-shot subset。

补充材料说 Stage 2 用 LoRA tuning 训练 1,000 steps。released config 4_dmd_long.yamltrain_lora: True。released config 4_dmd_long.yaml 中 LoRA rank: 256alpha: 256。两阶段设计的直觉是从易到难。先让模型学会在干净历史上生成下一镜头。再让模型学会在自己的不完美历史上继续故事。

3.6 代码映射与伪代码

公开仓库已经发布训练与推理代码。代码基线 commit 是 main@7ddcfaef,日期为 2026-03-31。README.md 给出环境、checkpoint 下载、推理和训练命令。tools/inference/causal_fewsteps.sh 调用 Inference_Causal.py。该脚本使用 --config_path ckpts/shotstream.yaml。该脚本使用 --resume_ckpt ckpts/shotstream_merged.pt。该脚本打开 --multi_caption True。该脚本读取 demo/testdata/testset.csv

Inference_Causal.py 读取 config、合并 default config,并实例化 CausalInferenceArPipelinepipeline/causal_inference_ar.py 实现 shot-by-shot 推理循环。pipeline/self_forcing_frameconcat_training.py 实现训练时的 chunk rollout 和 trajectory。model/dmd_frameconcat.py 实现 DMD frame-concat loss。

trainer/distillation_frameconcat_streaming.py 对应 streaming / long distillation trainer。tools/train/1_basemodel.sh 对应 teacher training。tools/train/2_ode_init.sh 对应 causal adaptation initialization。tools/train/3_dmd.sh 对应 intra-shot DMD/self-forcing。tools/train/4_dmd_long.sh 对应 inter-shot long rollout DMD。

# 伪代码,依据 pipeline/causal_inference_ar.py、README.md 和训练 config 抽象。
# 目标是表达真实代码路径,不是论文摘要重写。
 
def shotstream_inference(global_caption, shot_captions):
    output_shots = []
    shot_flags_for_rope = []
    for k, shot_caption in enumerate(shot_captions):
        if k == 0:
            condition_frames = zeros(max_context_frames=6)
            context_flags = [0] * 6
        else:
            condition_indices = dynamic_sample(output_shots, max_context_frames=6)
            condition_frames = gather_generated_frames(output_shots, condition_indices)
            context_flags = gather_shot_flags(condition_indices)
 
        context_latents = vae.encode(condition_frames)
        prompts = [global_caption + c for c in shot_captions[: k + 1]]
        text_cond = text_encoder(prompts)
 
        local_cache = init_local_kv_cache(window_chunks=7)
        context_cache = init_context_kv_cache(frames=len(condition_frames))
        current_noise = randn(frames=21)  # 7 chunks * 3 latent frames
        shot_flags_for_rope = context_flags + [max(context_flags) + 1] * 21
 
        current_shot = []
        for chunk in split_into_chunks(current_noise, chunk_size=3):
            pred_chunk = four_step_causal_generator(
                chunk,
                context_latents=context_latents,
                text_cond=text_cond,
                local_cache=local_cache,
                context_cache=context_cache,
                shot_flags_for_rope=shot_flags_for_rope,
            )
            local_cache.update(pred_chunk)
            current_shot.append(pred_chunk)
 
        decoded = vae.decode(concat(current_shot))
        output_shots.append(decoded)
    return concat(output_shots)

这段伪代码中 dynamic_sample 对应论文的 context frame sampling strategy。 context_cache 对应 global context cache。 local_cache 对应 local context cache。 shot_flags_for_rope 对应 RoPE discontinuity indicator。 four_step_causal_generator 对应 DMD 蒸馏后的 causal student。 frames=21chunk_size=3 对应公开推理代码的 7 个 chunk。 代码中 first shot 使用零条件帧,这与“无历史镜头”的特殊情形一致。 multi-caption prompt 拼接在代码中由 global_captions[0][0] + shots_captions[0][i][0][0] 完成。 这也解释了为什么数据 CSV 需要同时提供 global caption、shot captions 和 shot flags。

4. Experimental Setup (实验设置)

4.1 模型与数据

基础模型是 Wan2.1-T2V-1.3B。 输出视频分辨率为 。 论文训练 teacher 使用内部 curated dataset。 数据集规模为 320K multi-shot videos。 每个视频包含 2 到 5 个 shots。 每个视频最多 250 frames。 每个样本有层级 prompt。 global caption 描述 narrative arc、characters、visual style。 shot-level captions 描述每个镜头内的动作和内容。 公开仓库提供 demo 数据,但不是论文完整训练集。 README 也提示 demo captions 与实际训练/推理分布不同。 因此复现实验时,公开代码可验证流程,但不能仅靠 demo 数据复现论文指标。

4.2 训练阶段

Teacher training:只训练 DiT block 的 3D self-attention layers。Teacher training:Adam optimizer。Teacher training:学习率 。Teacher training:batch size 64。Teacher training:补充材料写 10,000 steps。Causal adaptation initialization:student 从 teacher 权重初始化。Causal adaptation initialization:采样 5K teacher ODE solution pairs。

Causal adaptation initialization:训练 all parameters。Causal adaptation initialization:2,000 steps。Causal adaptation initialization:学习率 。Causal adaptation initialization:batch size 64。Stage 1 DMD:intra-shot self-forcing。Stage 1 DMD:ground-truth historical shots。Stage 1 DMD:约 500 steps 收敛。Stage 1 DMD:batch size 32。

Stage 1 DMD:generator lr 。Stage 1 DMD:critic lr 。Stage 1 DMD:DMD2 风格 generator/critic 更新。Stage 2 DMD:inter-shot self-forcing。Stage 2 DMD:5-shot subset。Stage 2 DMD:模型生成 5-second shots。Stage 2 DMD:每到 shot boundary 更新 global cache 并重置 local cache。Stage 2 DMD:LoRA tuning 1,000 steps。所有实验训练在 32 张 NVIDIA H800 GPU 集群上完成。

4.3 公开代码中的配置锚点

tools/train/config/1_basemodel.yamltrainer: wan_frame_concattools/train/config/1_basemodel.yamlonly_train3d: Truetools/train/config/1_basemodel.yamldynamic_sample_frames: Truetools/train/config/1_basemodel.yamlchange_rope: Truetools/train/config/1_basemodel.yamlmax_context_frames: 6

tools/train/config/1_basemodel.yamllr: 1.0e-05tools/train/config/1_basemodel.yamltotal_batch_size: 64tools/train/config/2_ode_init.yamltrainer: ode_regressiontools/train/config/2_ode_init.yamlresume_ckpt: ckpts/bidirectional_teacher.pttools/train/config/2_ode_init.yamllr: 1.0e-06

tools/train/config/2_ode_init.yamltotal_batch_size: 64tools/train/config/3_dmd.yamltrainer: score_distillation_frameconcattools/train/config/3_dmd.yamlresume_ckpt: ckpts/ode_init.pttools/train/config/3_dmd.yamlresume_ckpt_real: ckpts/bidirectional_teacher.pt

tools/train/config/3_dmd.yamlresume_ckpt_fake: ckpts/bidirectional_teacher.pttools/train/config/3_dmd.yamldistribution_loss: dmd_frameconcattools/train/config/3_dmd.yamllr: 2.0e-06tools/train/config/3_dmd.yamllr_critic: 4.0e-07tools/train/config/3_dmd.yamlnum_frame_per_block: 3

tools/train/config/4_dmd_long.yamltrainer: score_distillation_frameconcat_streamtools/train/config/4_dmd_long.yamlresume_ckpt: ckpts/shotstream_merged.pttools/train/config/4_dmd_long.yamltrain_lora: Truetools/train/config/4_dmd_long.yaml:LoRA rank: 256alpha: 256

tools/inference/causal_fewsteps.sh:公开推理入口是 python Inference_Causal.pytools/inference/causal_fewsteps.sh:加载 ckpts/shotstream.yamlckpts/shotstream_merged.pttools/inference/causal_fewsteps.sh:使用 --multi_caption True

4.4 评测集、指标与 baselines

评测集由 Gemini 2.5 Pro 生成 100 个多样 multi-shot video prompts。为公平比较,论文把 prompts 改写为适合各 baseline 的输入风格。这些 prompts 覆盖多种主题,用于测试跨场景一致性。计算指标前,论文使用 TransNet V2 检测 shot boundaries。Intra-shot Subject Consistency 使用 DINO cosine similarity。Intra-shot Background Consistency 使用 CLIP similarity。

Inter-shot subject/background consistency 使用 YOLOv11 和 SAM 分离 keyframes 后,用 DINOv2 评估。Inter-shot semantic consistency 使用 ViCLIP feature cosine similarity。Transition Control 使用 Shot Cut Accuracy (SCA)。Prompt Following 使用 Text Alignment。Overall Quality 报告 VBench 的 Aesthetic Quality 和 Dynamic Degrees。

Bidirectional baselines 包括 Mask2DiT、EchoShot、CineTrans。Autoregressive / interactive baselines 包括 Self Forcing、LongLive、Rolling Forcing、Infinity-RoPE。推理效率在单张 NVIDIA H200 GPU 上评估。

5. Experimental Results (实验结果与评价)

5.1 主定量结果

ShotStream 的 FPS 是 15.95。摘要和项目页四舍五入称其达到 16 FPS。相比 Mask2DiT 的 0.149 FPS,吞吐提升约 107 倍。相比 EchoShot 的 0.643 FPS,吞吐提升约 24.8 倍。相比 CineTrans 的 0.413 FPS,吞吐提升约 38.6 倍。论文文本概括为相对 bidirectional models 超过 25 倍 FPS 提升。ShotStream 的 intra-shot subject consistency 是 0.825。ShotStream 的 intra-shot background consistency 是 0.819。

ShotStream 的 inter-shot semantic consistency 是 0.762。ShotStream 的 inter-shot subject consistency 是 0.654。ShotStream 的 inter-shot background consistency 是 0.645。ShotStream 的 transition control 是 0.978。ShotStream 的 text alignment 是 0.234。ShotStream 的 aesthetic quality 是 0.571。ShotStream 的 dynamic degree 是 63.56。

Dynamic degree 的最高值来自 EchoShot 65.92,ShotStream 是第二高。除 dynamic degree 外,ShotStream 在表中主要一致性和控制指标均为最佳。这说明它并非单纯牺牲画质换速度。它同时提高了跨镜头语义、主体、背景一致性。最关键的指标是 transition control 0.978。这比 LongLive 的 0.693、Rolling Forcing 的 0.684 和 Infinity-RoPE 的 0.715 高很多。这说明 ShotStream 的多镜头边界控制明显强于普通长视频自回归 baseline。

100%

qualitative comparison 中,Mask2DiT、CineTrans、Self Forcing、Rolling Forcing 未能稳定跟随各镜头 prompt。 EchoShot 和 Infinity-RoPE 能适应单个镜头指令,但跨镜头一致性不足。 LongLive 会混淆连续出现的两位女性身份。 ShotStream 同时保持 prompt adherence、视觉连贯和自然切换。 这个现象与表格结果一致。 即 transition control 和 inter-shot consistency 是它的主要优势。

5.2 用户研究

用户研究随机抽取评测集中的 24 个 multi-shot prompts。 参与者人数为 54。 每次对比同时展示 8 个视频。 8 个视频包含 ShotStream 和 7 个 baselines。 展示顺序随机化。 参与者从 Visual Consistency、Prompt Following、Visual Quality 三个维度选择偏好视频。 允许多选。 Visual Consistency 偏好率:ShotStream 87.69%。 Prompt Following 偏好率:ShotStream 76.15%。 Visual Quality 偏好率:ShotStream 83.08%。 第二梯队在 Visual Consistency 上是 Infinity-RoPE 16.92%。 第二梯队在 Prompt Following 上是 LongLive / Rolling Forcing 16.15%。 第二梯队在 Visual Quality 上是 Rolling Forcing 23.08%。 因为允许多选,百分比不需要加和为 100%。 这些结果说明 ShotStream 的主观优势不是只来自某一个维度。 用户同时感知到了跨镜头一致性、文本跟随和视觉质量提升。

5.3 Teacher 设计消融

Context Frames Sampling Strategy 中,First Only 的 inter-shot semantic 是 0.671。First & Last 的 inter-shot semantic 是 0.709。Dynamic sampling 的 inter-shot semantic 是 0.762。First Only 的 transition control 是 0.956。Dynamic sampling 的 transition control 是 0.978。Dynamic sampling 的收益说明“最近镜头余量分配”比固定抽帧更适合叙事续写。

Condition Frames Captioning Strategy 中,Target Caption 的 text alignment 是 0.194。Multi-Captions 的 text alignment 是 0.234。Target Caption 的 aesthetic quality 是 0.422。Multi-Captions 的 aesthetic quality 是 0.571。这表明历史帧对应的文本标签会影响模型对历史的理解。Condition Injection Mechanism 中,Channel Concat 的 inter-shot semantic 是 0.743。

Frame Concat 的 inter-shot semantic 是 0.762。Channel Concat 的 transition control 是 0.912。Frame Concat 的 transition control 是 0.978。Training Strategy 中,Full fine-tuning 的 dynamic degree 是 60.85。Only 3D 的 dynamic degree 是 63.06。Full fine-tuning 的 inter-shot background 是 0.624。Only 3D 的 inter-shot background 是 0.645。

因此 teacher 最终选择 dynamic sampling、multi-captions、frame concat、only 3D self-attention tuning。

5.4 Causal student 设计消融

100%

Dual-Cache Distinction Strategy 中,w/o Indicator 的 inter-shot semantic 是 0.728。Learnable Emb.的 inter-shot semantic 是 0.737。RoPE Offset 的 inter-shot semantic 是 0.762。w/o Indicator 的 inter-shot subject 是 0.507。Learnable Emb.的 inter-shot subject 是 0.518。RoPE Offset 的 inter-shot subject 是 0.654。w/o Indicator 的 inter-shot background 是 0.465。

Learnable Emb.的 inter-shot background 是 0.588。RoPE Offset 的 inter-shot background 是 0.645。这说明显式 RoPE discontinuity 对跨镜头主体和背景尤其关键。Learnable embedding 有帮助,但不如训练无关的 RoPE offset 稳定。Causal Distillation Training Strategy 中,Stage 1 Only 的 inter-shot subject 是 0.604。Stage 2 Only 的 inter-shot subject 是 0.583。Two Stage 的 inter-shot subject 是 0.654。

Stage 1 Only 的 dynamic degree 是 59.66。Stage 2 Only 的 dynamic degree 是 52.86。Two Stage 的 dynamic degree 是 63.06。Stage 1 Only 的 aesthetic quality 是 0.568。Stage 2 Only 的 aesthetic quality 是 0.467。Two Stage 的 aesthetic quality 是 0.571。这说明单独 Stage 2 并不能替代 Stage 1。Stage 1 提供稳定的 next-shot 基础。

Stage 2 负责把历史分布从 ground-truth history 推到 self-generated history。两者组合才符合真实推理链。

5.5 复现性、局限与代码判断

代码已公开,且 Hugging Face 模型页面也已公开。arXiv 页面当前写明 training/inference code 和 models available。项目页文本仍保留 “Code and models will be released.” 的旧说法,但页面顶部和 HF model 已链接到公开资源。公开 repo 允许验证 pipeline、config、DMD loss 和推理入口。训练数据不是公开的完整 320K 内部数据集。因此公开代码更适合做方法复现和 demo 推理,而不是完整复现论文表格。论文没有详细公开 100 个 Gemini 2.5 Pro prompts 的完整列表。论文也没有公开所有内部 captioning 和数据筛选策略。

指标涉及 YOLOv11、SAM、DINO/DINOv2、ViCLIP、VBench、TransNet V2,多组件评测复现成本较高。对实际使用者而言,最有价值的可复现线索是推理脚本和 checkpoint。bash tools/setup/download_ckpt.sh 下载 Wan2.1-T2V-1.3B 和 ShotStream ckpts。bash tools/inference/causal_fewsteps.sh 运行 autoregressive 4-step long multi-shot generation。若要二次开发,优先读 pipeline/causal_inference_ar.py

若要训练复刻,按 README 顺序读 tools/train/1_basemodel.sh2_ode_init.sh3_dmd.sh4_dmd_long.sh。若要理解 loss,优先读 model/dmd_frameconcat.py。若要理解缓存,优先读 pipeline/causal_inference_ar.py_initialize_kv_cache_initialize_context_kv_cache。若要理解数据格式,读 demo/testdata/testset.csvutils/dataset.py。论文方法的主要风险在于内部数据依赖和评测复杂度。

论文方法的主要工程优势在于把 interactive storytelling 的需求落到了明确的 cache、RoPE flag 和 staged rollout 上。我的判断:ShotStream 是一个偏工程系统完整性的贡献,而不是单一 loss 或单一 attention trick。它的关键成功条件是 teacher 数据质量、dual-cache 边界编码和 Stage 2 rollout 训练共同成立。