资讯动态

长视频生成如何保持一致性:选择性空间记忆机制解析

发布时间:2026/10/26 8:10:33 来源:尧图企业网站定制
Long-Horizon Video Generation 最近是真的热。扩散模型把单帧、短视频的生成质量拉到很高之后大家马上发现一个绕不开的瓶颈一旦要生成几分钟甚至更长的视频模型就会“失忆”——角色偷偷换衣服、场景里家具移位、物体凭空消失再冒出来。最近看到 Keepsake 这个项目它把问题归结为缺少一种选择性空间记忆Selective Spatial Memory思路相当清楚。这篇文章就结合我的复现和试验经验聊聊长视频生成里记忆机制为什么关键以及 Keepsake 这类设计是怎么把“记忆”做成可学习、可查询、可控制的。我自己的感受是现在大部分视频生成模型的“记忆”本质上是借用了语言模型的上下文窗口或者干脆不设计记忆只靠时序连续性。这在短视频上没问题但一旦进入长时程生成所有问题都会暴露出来。Keepsake 这类工作最大的价值就是明确把“记忆”从一个模糊概念拆成了可监督的空间结构。所以这篇文章会从问题拆解、方案设计、训练调参和踩坑几个角度把这个方向讲透。1. 长视频生成到底“难”在哪先搞清楚要解决什么问题1.1 越生越歪的“断片”现象场景、角色、风格全在漂移我先说一个大家肯定都遇到过的现象让模型生成一个角色穿过街道的视频前十秒头发颜色、衣服款式都正常但越往后越不对劲角色可能换了外套颜色或者路人甲的脸重复出现甚至某个背景建筑悄悄变了结构。这种问题在行业里叫 temporal inconsistency翻译过来就是时序不一致。为什么核心原因很简单视频生成模型通常是逐帧或逐块生成每一帧都依赖前面的帧。但前面帧的信息无法无损地传递下去。从概率角度看模型在每一步都在估算条件分布误差会像滚雪球一样累积。哪怕单帧误差只有1%生成300帧之后整体内容可能已经面目全非。传统方法里常用隐状态hidden state来记忆比如ConvLSTM但隐状态容量有限早期的细节早就被挤压成了模糊的平均信息。举个生活类比让你复述一个半小时前看过的电影你大概能记住主线剧情和几个关键画面但演员在那个场景穿了什么颜色的鞋、桌子上的摆设位置你基本说不出。视频生成模型也一样它不知道哪些细节值得长期保留于是干脆把所有东西都“平均”掉。而长视频想要有“电影感”恰恰靠的就是这种细节的连续可信。所以要解决长时程生成问题第一步就是设计一个能长期保存关键信息的记忆系统。1.2 把上下文窗口当记忆用为什么吃不下long-horizon现在很多模型靠的是Transformer架构天然支持长上下文。于是有人会想我把过去所有帧的token全部拼起来作为条件不是就有记忆了吗问题是这根本走不通。先把账算一下一段10秒的视频24fps就是240帧。每帧经过VQVAE或类似编码器压缩后仍然可能有上百个token。240帧就是两三万个token。生成后面的内容时模型要考虑所有这些token计算量随序列长度平方增长显存直接爆炸。即便用FlashAttention之类的工程优化上下文的“长度”解决了但“精度”依然不够——模型需要在几万个token里找一个特定位置上的微小细节注意力权重会被平均化分摊关键信息反而被淹没。还有一种做法是把整个视频压缩成一个全局特征向量然后作为条件注入。这种做法的毛病更大全局向量是对所有帧的“平庸总结”你让它记住主角的左脸有一道疤它根本做不到因为向量里已经没有空间分辨能力了。相比之下Keepsake 这类工作把记忆拆成空间局部单元就相当于给模型一个“外挂硬盘”而且这个硬盘是有坐标的需要查什么位置的细节就去对应坐标读取而不是翻整部电影。1.3 从“全部记住”到“选择性记住”Keepsake的核心思路这里就引出了 Keepsake 标题里的关键词Selective Spatial Memory。选择性是指在合适的位置遗忘不重要的信息而空间性是指记忆是按二维位置组织和检索的。为什么强调选择性因为记忆资源永远是有限的。显存有限、注意力容量有限、训练数据里的信息也有冗余。你要是不加选择地把所有帧的所有特征全存下来不仅仅是浪费问题更是噪声问题很多背景区域在视频里是不变的反复存它们只会让特征之间的区分度下降。好的记忆机制应该只记住“值得记住的”内容比如前景对象的身份、外观、位置以及场景中显著的结构性物体而忽略纹理、光照变化等相对低价值的细节。为什么强调空间性因为视频里的一致性本质上体现为空间位置上的连续性。角色从画面左边走到右边他的脸在空间位置上是连续移动的。如果记忆只保存“特征向量”那这个向量和一个“是什么东西”没有区别丢失了“在哪”这一维度。一旦丢失了空间坐标后续生成时你无法确定从记忆里取出的特征该对应画面中的哪个区域物体自然就容易乱跑。所以明确的二维坐标索引是长时程视频记忆的刚需这也是空间记忆与片段记忆、语义记忆最大的差别。2. 选择性空间记忆的设计拆解Keepsake 是怎么记住该记的2.1 为什么记“空间”而不是记“语义”世界是三维连续的视频本质上是对一个三维、随时间变化的场景进行二维投影。生成时只要保证每个空间位置上的对象身份稳定画面在直觉上就会连续。而语义特征往往是对整幅画面或某个区域的压缩描述比如“这是一个穿着红色裙子的女人”但“女人”在画面中的具体坐标、掩码形状都已经丢失了。空间记忆的做法是把画面划分成带坐标的小格子每个格子里存高维特征。这些特征既描述了“这是什么”也记录了“它在这里”。当后续生成需要某个区域的上下文时模型直接按坐标查询找到该坐标周围历史上出现过的特征然后融合进当前的生成过程。这样做的好处是区域间的自然遮挡、运动都能用一个统一的坐标映射来处理。以常见的视频编码结构为例你可以把记忆库看成一个尺寸为 H×W×D 的隐形特征图H和W等于视频特征图的空间尺寸D是特征维数。这个特征图有一个时间戳或者置信度用于表示最近是否被更新过。每当新的视频帧经过编码器我们就得到一组新的空间特征然后决定哪些位置的特征需要覆盖、哪些位置保留旧值。这种设计天然适合像扩散模型U-Net这类既有空间又带注意力的骨干网络。2.2 空间记忆库的结构从稀疏特征到可查询的map具体实现上记忆库通常会分成两个部分一个是“主记忆区”保存跨帧累积的一致特征另一个是“工作记忆区”保存当前片段的短期上下文。主记忆区负责回答“这个场景里原本有什么”工作记忆区负责回答“现在正在发生什么”。Keepsake 标题中的“Keepsake”有“纪念品”的意思也暗示了记忆库应该保存的是那些高价值、值得长期保留的片段而不是流水账。我见过比较合理的做法是让记忆库位置只覆盖显著区域也就是稀疏的。全图的稠密记忆不仅浪费资源还会引入大量静态区域的冗余特征。可以用一个轻量显著度网络或者直接取特征响应幅度较大的位置作为候选写入点。这样每个时间步只更新几百个位置而这些位置通常就是前景对象、物体边缘和动态区域。查询过程非常像数据库操作当前帧对应坐标上的特征作为 query去和记忆库中同一坐标邻域内的 keys 做内积得到相似度再按相似度加权求和返回一个“融合了历史信息”的特征。这个操作可以用注意力机制实现而且完全支持端到端反向传播。为了保证空间连续性可以加上位置编码甚至可以支持软查询也就是说 query 的坐标不一定是整像素小数坐标也可以插值读取。这一点对运动特别重要因为物体不会每次都乖乖停留在整格坐标上。2.3 可微的门控和注意力一定得能反向传播很多人在设计记忆模块时容易写出一堆“不可微”的规则比如“如果相似度大于阈值就覆盖否则保留”。这种硬规则在训练时无法把梯度传回编码器会让整个记忆系统变成固定缓存缺乏适应性。理想的门控应该让“写入多少”和“读取多少”都是网络学出来的软注意力系数。以写入门控为例新特征和历史特征之间计算一个相似度经过sigmoid得到一个0到1之间的权重。权重接近1时代表该位置需要完全用新特征更新权重接近0时代表该位置保持不变。最终写入值 门控系数 × 新特征 (1 - 门控系数) × 旧特征。这个公式就是LSTM门控思路的空间版本既能保存长期信息又能防止每次微小的输入波动导致记忆振荡。读取门控也类似当前帧的查询特征与所有候选记忆项都有相似度。相似度经过softmax得到注意力权重然后把记忆值加权求和。这里还有一个细节为了避免模型偷懒总是读取同一个记忆位置最好加一个“查询一致性”的正则让读取权重在空间上尽量集中减少“各取所需”导致的特征混淆。2.4 和扩散生成模型的对接记忆怎么参与去噪过程Keepsake 这类机制要落地最关键的是怎么塞进现有的视频生成框架。目前主流是扩散模型生成过程是一个从纯噪声逐步去噪到清晰视频的过程。在每一个去噪step里UNet会接收噪声帧和条件信息比如文本通过cross-attention注入语义条件。记忆模块可以选两个位置插入。一种是把记忆当作额外的条件在UNet的cross-attention层里和文本特征拼在一起让UNet同时注意到文本和记忆另一种是直接调整UNet的时间层和自注意力层把记忆特征作为自注意力的KV来源。我倾向于前者因为改动小、兼容性好且可以把记忆模块当成一个插件很方便地挂在现有开源模型后面。要注意的是记忆参与生成的时间粒度。如果每一帧、每个噪声step都动态查询记忆开销会很大。更经济的做法是每生成一段比如8帧后把已经生成的帧输入编码器提取新记忆并更新记忆库然后下一个片段生成时记忆库里的信息作为持久条件。这样就形成了“生成片段—更新记忆—继续生成”的循环既保证长程一致性又不会让计算成本爆炸。3. 训练与调参从论文到能跑的若干实操细节3.1 数据准备长时间一致性的视频比想象中难搞巧妇难为无米之炊。要训练记忆模块你需要有足够多的“长视频且内容前后一致”的数据。但现实是公开视频数据集大多由短视频拼接而来跨镜头时场景完全跳变根本没有长期一致性可言。若直接拿来训练模型学到的反而是“大量变化才是常态”它的记忆会趋于混乱。我建议的做法是从长视频中用镜头检测算法比如PySceneDetect切出多个连续镜头每个镜头单独作为一条训练样本。关键是要保证场景内没有频繁变亮的闪光、阴影变化和镜头抖动否则记忆模块会把光度变化当成内容变化去更新浪费记忆容量。数据增强也要小心。长视频目标通常是保持一致性所以不能过多使用颜色抖动、随机裁剪等破坏空间对应关系的增强。可以做的增强是轻微的时间平移、轻微模糊和尺度扰动。如果做多尺度空间特征训练要注意保持坐标映射关系一致否则记忆库的索引就彻底乱套了。3.2 训练目标重建、对比、和记忆正则记忆模块的训练不能只靠视频重建损失这会让记忆退化成低通滤波。最直接的办法是加一个“记忆读取损失”在训练时强制要求从记忆库读取的特征和当前帧对应的真值特征余弦相似度足够高。也就是模型必须学会把关键信息写进记忆而不仅仅是保存残差。另一个很实用的是对比学习。随机把某个前景物体遮住然后使用记忆查询看能否找到该物体的历史特征。正样本是该物体在当前帧的特征负样本则是背景区域、其他物体的特征。通过这种对比训练记忆库里的每个位置才会有明确的身份语义而不是一团平均颜色。你会发现对比损失加对了之后记忆特征之间的簇状分布更明显读出来的特征也更“锐利”。还需要一个“遗忘正则”防止记忆库饱和过度。如果门控权重总是接近于1那就意味模型总是在覆盖旧记忆这会让长期记忆完全失效。可以通过在门控输出上增加一个均值约束让整体覆盖频率保持在某个合适的区间比如0.3到0.7之间。这个数值我试下来很敏感需要根据视频的物体运动频率调整。3.3 记忆容量的平衡不同场景下该给多少token记忆容量到底设多大这是大家最容易纠结的地方。很多人下意识觉得容量越大越好结果在实际训练里显存爆炸而且记忆太拥挤之后注意力会互相干扰。实际上容量应该根据场景复杂度动态调整。我的经验是以常见的16:9视频为例特征图空间尺寸如果是H/8 × W/8比如64×112全图有7168个位置但大部分位置是静态背景不必都存。我通常只选取响应最高的512~1024个区域作为候选记忆token。每个token的向量维度取64~128。如果场景里杂物很多可以适度增加到2048但再多效果反而下降。这里有个直觉原因记忆查询本质上是坐标空间内的一个信号检索过程。位置越多单个位置的区分度就必须越高否则容易出现“读错人”的情况。就像图书馆里书架越密集图书号必须越精确否则随手一抽就是另一本书。容量和区分度投资存在一个拐点预算有限时小而精优于大而全。3.4 渐进式长度训练别一上来就生成几万帧记忆模块的训练对长度非常敏感。如果刚开始训练就上手256帧连续生成模型可能要花大量时间在维持画面稳定上而记忆模块的梯度根本来不及传到早期帧。我试过直接训练时loss降到一定程度就不再下降记忆库基本上只记住最近几帧。更好的做法是渐进式长度训练先在16帧或32帧的小片段上训练让模型学会最基本的内容重建然后逐步增加片段长度到64、128、256帧。每次增加长度时可以降低学习率同时增加一个“记忆一致性”的辅助loss权重促使模型学会利用记忆而不是仅仅依赖短程隐状态。这种课程学习思路在超长视频生成里几乎是必须的训练稳定性会明显好很多。另外优化器上有一些细节。记忆模块的参数更新通常比主干网络更慢所以我建议给它单独设一个学习率可能是主干学习率的一半或者三分之一。否则很容易出现主干已经拟合得很好记忆模块还在剧烈震荡导致生成画面周期性地“闪烁”。4. 复现过程中最常见的坑和排查手段4.1 记忆污染两个相似场景互相干扰长视频中经常会发生场景来回切换的情况比如角色在“客厅”和“卧室”之间走动。如果记忆库没有场景边界概念客厅里的沙发特征可能被误写进卧室的记忆位置导致模型生成卧室时莫名出现沙发。这是一个我在实际复现中最头疼的坑属于记忆污染。排查方法并不难你把记忆库特征做个可视化看看不同时间提取的特征是否混合在相同位置。可以按时间步输出记忆库特征的前几个主成分观察它们是否随时间清晰聚类在几个“模式”上。如果聚类很模糊大概率是记忆被污染了。常见的解决思路有三种一是加入场景边界检测检测到镜头切换时就重置记忆库二是让记忆读入门控学习一个“场景标签”条件只有标签一致时才能写入三是给记忆库增加一个“写保护”机制相似度过低的新特征不被写入。我个人实际用下来最有效的是“软重置写保护”组合在镜头切点把记忆库的置信度清零然后在后续几帧逐渐重建记忆。这样既不会立刻丢失所有信息也不会让新场景内容与旧场景内容混在一起。4.2 坐标漂移物体从左边跳到右边空间记忆的坐标不是固定的因为镜头在动、物体在动。如果你用固定特征图坐标来存记忆一个移动物体在不同帧会出现在不同坐标上查询时如果你只查询当前坐标邻域可能找不到它过去的历史特征导致物体身份突变。我在复现时遇到最典型的现象就是一个人从画面左边走到右边后如果镜头切回左边模型很有可能生成另一个相似但不同的角色。原因就是记忆库按坐标索引而角色的历史特征被存在了之前的坐标位置读取时没有根据运动偏移去对应。解决这个问题的通用做法是引入光流对齐。在把新特征写入记忆库之前先用光流或可学习的变形网格把特征“搬”到当前坐标查询时同理把记忆库中特征点也顺着运动方向平移一段使得新旧特征能在同一个坐标系下对碰。如果不想引入额外的光流模型也可以用连续位置编码和可变形注意力来隐式处理让网络自己学会从小邻域内聚合信息。效果上可变形注意力更方便因为它不需要额外监督可以在主任务loss的驱动下自行学习采样偏移。4.3 显存爆炸记忆库也是要钱的很多人觉得记忆模块就是一个张量占不了多少显存但真正用起来才明白记忆库的存储开销远不是那个张量本身而是围绕它的读取、更新、梯度传播过程中产生的一系列中间值。在训练长视频时如果你把记忆库的批次维度设得很大显存很容易直接爆掉。我的实际做法是把记忆库的更新过程分段化。训练时不要每个step都保留完整梯度链。可以采用“冻结记忆库部分梯度”的策略每更新4~8帧记忆后对后续帧的loss进行反向传播但之前帧的记忆更新路径可以用stop-gradient截断。这样虽然牺牲了长时间端到端的可微性但训练速度也快了很多显存开销能降下50%以上。另一个技巧是在记忆查询时使用top-k而不是全量注意力。比如每个query只在记忆库的top-32或者top-64的候选里做注意力这可以大幅减少注意力矩阵的计算量和显存占用。毕竟真正对当前帧有用的历史信息是稀疏的没必要让每个query都看全部的记忆库。4.4 生成质量与一致性的trade-off为什么加了记忆反而变糊加了记忆模块之后最常见的一个副作用是画面变“糊”或者细节“平均化”。原因是记忆特征是一种压缩过的空间特征如果把读取到的记忆特征强行注入到当前生成中但当前帧的细节与历史细节之间本来就有差异融合后就会产生“多帧平均”的感觉尤其是衣服纹理、毛发这种高频信息。我一开始以为问题出在记忆读取权重上调高读取权重后反而更糊因为高频信息被低频平均覆盖了。后来发现正确做法是在去噪过程中早期step大概前40%增加记忆信息的注入强度负责确定主体结构和身份后期step要大幅降低记忆的参与让模型专注生成当前帧的高频细节。相当于“先靠记忆画出轮廓再靠生成本能填细节”。同时建议在特征融合时加入一个可学习的缩放因子初始值设得很小比如0.1让模型自己决定每个位置需要多大比例的历史特征。训练初期这个缩放因子会变大而训练后期会自动收敛到一个合适区间。如果发现最终收敛的缩放因子很小说明你的记忆特征对当前帧的帮助不够这时检查一下记忆写入的后台是否在做无用的特征覆盖。5. 哪些应用场景最需要 Keepsake 这类机制5.1 超长视频生成电影级镜头叙事的可能现阶段AI生成视频多数停留在短视频范畴10秒甚至20秒就已经需要“运气”。但真正的影视创作、商业广告、游戏过场动画需要的都是持续几十秒甚至几分钟的镜头。这里面最核心的并不是分辨率而是所有镜头元素的前后一致。角色一旦中途换发型观众立刻就出戏。Keepsake 这类选择性空间记忆恰好是解决这个“行业级痛点”的路径。在生成一个长镜头时角色脸部的“空间记忆”可以持续保留即便镜头切换角度、他转身离开再回来模型依然能通过记忆查询把他的脸部特征复原到当前画面。这种能力会直接让生成式视频制作进入“可规划”的阶段而不是像现在这样靠抽卡。5.2 交互式/具身智能仿真场景必须持续一致另一个我非常看好的方向是具身智能和交互式仿真。机器人在虚拟环境中探索时需要在连续时间里感知同一个世界这个房间里的椅子不能因为视角转了一圈就变成沙发抽屉打开之后内部结构要一直存在。这类需求本质上是“世界模型”的构建而世界模型的必要组件就是一张持续更新的空间记忆地图。Keepsake 的记忆设计天然和这类场景吻合。因为机器人处于一种“由动作驱动的视频生成”模式每一次行动都会改变周围环境记忆库需要选择性更新被改动的位置同时保留没变化的区域。就我目前看到的实验数据来说加了空间记忆模块的仿真环境在长程探索任务里的语义保持能力比普通帧序列模型高出不少而且不会出现“回到原地却发现世界重组”的荒诞错误。5.3 与现有模型的整合路径LoRA、Adapter还是替换注意力现在开源生态里有很多优秀的视频生成模型大家最关心的是Keepsake 这类模块能不能以低成本接入现有模型。我认为最稳妥的方式是做成一个简洁的“记忆Adapter”挂在UNet的外部。具体来说保留原模型的权重不变新增一个可训练的记忆编码器、记忆库和记忆注意力层。在每一段生成开始时用原模型的编码器提取当前帧特征通过记忆Adapter写入记忆库在后续生成时把记忆库特征作为额外的cross-attention条件注入UNet。所有新增参数可能只有原模型的10%~20%却可以显著改善长时一致性。这样做有几个好处首先你不需要重新训练庞大的主干模型极大地降低算力门槛其次如果未来出现更强的基础生成模型记忆Adapter可以直接迁移过去几乎不用改结构最后记忆Adapter的训练可以只靠长视频数据不需要收集额外的文本标注因为记忆本身不依赖文本条件。如果你手头有多卡资源完全可以把记忆Adapter训练成可以即插即用的独立插件发布。6. 从Keepsake想到的一些实操心得和后续方向6.1 记忆不是越大越好而是“遗忘”要合理在实际复现和调试中我最深的一个体会是设计一个“长期记忆”系统真正难的不是记住而是遗忘。很多实验为什么效果不好并不是模型记不住细节而是它没有学会“该记什么”。角色在画面里走路时背景树影每一帧都在晃动如果记忆模块把这些晃动的细节都当回事很快内存里全都是噪声真正的关键信息反而被挤掉。后来我尝试把门控设计成“自适应遗忘”模式让网络自己判断某个区域是否需要更新。随着时间的推移记忆库对某些位置的置信度会逐渐降低如果这个区域的新旧特征持续冲突置信度就更低查询时权重也会更小。这个设计的直观效果是画面中稳定的物体特征越来越锐利而时隐时现的道具则不会对长期一致性造成干扰。你可以把这个过程理解成人脑的记忆巩固机制反复出现的信息进入长期记忆一次性的信息则被丢弃。6.2 后续可以扩展的方向从空间记忆到时空记忆Keepsake 目前强调的主要是“空间记忆”但视频本质上是一个三维时空连续体空间只是一部分。顺着这个思路下一个可以自然扩展的方向是“时空记忆”不仅仅记住物体当前在哪、长什么样还要记住它以前到过哪、运动轨迹如何。比如生成一个跑步的人记忆模块不仅要记住他的脸还要记住他的摆臂节奏和位移路径。这种时空对齐能力一旦建立起来模型就具备了初步的“物理直觉”能推测物体在下一段时间里可能出现在哪里生成出来的运动会更自然。另一个值得探索的方向是分层记忆。当前这个方案偏向于底层视觉特征记忆但叙事层面的记忆也很重要比如角色说过什么话、发生过什么关键事件。将视觉空间记忆和高层的语义记忆组织成一个层次化结构是长视频叙事的最终解法。这个方向现在挑战很大因为需要跨模态的数据和监督信号但一旦做通AI生成影视作品的逻辑性会提升一个档次。6.3 如果你想上手实验我建议从这三点开始如果你想复现类似思路我给出的建议很简单。第一找一个开源短视频生成模型做底座不要从零训练主流扩散模型成本太高第二先用强化学习或自监督方式训练记忆模块把视频重建和对比损失分开调搞清楚每个损失的作用第三从小规模数据验证而不是一上来追求超长视频先看32帧能否稳定保持角色身份再逐步加长度。你可能会发现加记忆模块前期会让训练速度变慢甚至初期效果比不加还差。这是正常的因为记忆模块需要时间和足够的训练信号才能学会“读写”。我在试验中把前几千步的学习率调低到原来的十分之一同时给记忆门控加了一个“auxiliary loss”来引导效果会好很多。希望大家少走这些弯路。长视频生成从来不是一个“够快够清晰”就完事的问题它更考验系统的长期一致性。而一致性最终要靠一套高质量的记忆机制兜底。Keepsake 把“选择性空间记忆”这个概念落地成了一个可训练、可组合的模块在我看来是相当有价值的方向。后续谁能把记忆和生成做到更聪明的协作谁就能真正解决长视频生成落地的问题。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑