
最近技术圈里“连续时间具身世界模型”“任意帧率自由生成”这两个提法频繁出现标题里甚至在强调“全球首个”。作为做生成模型和具身智能相关工作的开发者我第一反应不是跟着喊口号而是想把它拆开看所谓“连续时间”到底改变了什么任意帧率自由生成在算法上是怎么做到的如果我要在一个最小 demo 里复现这个思路需要解决哪些问题这篇文章就围绕这几件事展开先讲清楚连续时间世界模型是什么再拆解“任意帧率生成”的核心原理接着给出一个可以运行的最小 PyTorch 实现从数据构造、模型训练到任意帧率推理走完整条流程最后整理工程落地时的常见问题和最佳实践。内容偏系统教程向新手可以理解概念有基础的同学可以直接跳到第 3、4 节看代码和训练逻辑遇到问题再回来看第 5、6 节。1. 背景与核心概念1.1 “全球首个”背后我们在关注什么“全球首个”通常是研究团队或产品团队对外传播时的口径从技术角度很难严谨核实也不适合单纯按发布时间判断价值。真正值得关注的是它背后有没有解决旧的离散时间世界模型解决不了的问题以及“连续时间 任意帧率”是不是一个可复现的算法设计。换句话说与其关注“谁是第一个”不如关注“这条技术路线为什么成立”。如果一个框架能统一建模连续变化的物理过程并且可以在推理阶段按任意帧率输出结果那它对仿真、机器人决策、视频生成都会有实际价值。本文不评价具体团队和竞品只讨论技术本身。1.2 世界模型是做什么的世界模型World Model可以理解成“让模型学会环境如何随动作变化”的内部模型。早期比较有代表性的工作把世界模型放在策略学习和规划中智能体看到的不是原始画面而是一个压缩后的潜在状态模型在这个潜在空间里预测下一步会发生什么。后来很多基于强化学习的算法都把“预测未来”“想象未来”当成核心能力。世界模型被广泛用在以下场景在游戏环境中学习环境动态然后让智能体在“想象”中做规划减少真实环境交互。在机器人操作任务中根据当前图像和机械臂动作预测下一时刻状态用于控制或评估策略。在视频生成领域模型学会给定历史帧和动作条件生成未来帧本质上也是一种图像层面的世界模型。传统世界模型通常按固定时间步长工作比如每 30ms 或每 30 帧预测一次。这样做实现简单但一旦真实系统的控制频率和训练用的频率不一致问题就来了。1.3 具身世界模型与通用视频生成模型的区别具身世界模型Embodied World Model更强调“智能体本身也在环境中”。它不只是预测画面还要刻画“当前状态 → 动作 → 下一状态”的因果过程。比如机械臂抓取物体时模型需要理解机械臂关节角的变化、接触力反馈、物体位置变化甚至多传感器之间的时序关系。通用视频生成模型通常只从文本、图片或历史视频条件生成未来视频它不关心“为什么画面会这样变化”也不一定建模动作。具身世界模型则必须建模动作和状态之间的耦合否则生成的画面再好看也无法指导机器人做出正确决策。这带来一个额外要求状态的“时间语义”必须准确。机械臂在 1.000 秒时刻的位置和 1.033 秒时刻的位置是不同的如果模型只能处理固定帧率那么控制回路的时序精度就无法保证。1.4 连续时间与任意帧率带来的变化连续时间世界模型把时间从一个离散索引变成一个连续变量。模型学习的是“在任意查询时刻 τ预测未来状态”这样的映射函数。这个设计直接影响任意帧率生成推理时你希望生成 10fps 视频就每隔 0.1 秒查询一次。希望生成 60fps就每隔 1/60 秒查询一次。希望做慢动作或关键帧补全就针对任意时刻 τ 单独查询。希望做非均匀时间间隔采样也完全可行。同一个模型不再需要为每种帧率单独训练也不需要先训练高帧率再下采样。这是连续时间建模带来的直接收益。2. 连续时间建模的核心原理2.1 离散时间模型的瓶颈离散时间模型的基本形式可以写成s_{t1} f(s_t, a_t)也就是从当前状态 (s_t) 和动作 (a_t) 预测下一个固定间隔的状态 (s_{t1})。这里的时间间隔是隐藏的常量模型不会显式感知它。这样做有三类问题帧率不匹配。训练时数据是 30fps到了机器人部署环境控制循环可能跑 100Hz此时 30fps 的预测就不够用了。补帧困难。想从 30fps 插值到 60fps需要额外训练一个专门的插值模型成本高且容易造成运动不连贯。时间语义缺失。模型不区分“过了 10ms”和“过了 100ms”它只知道“往下走一步”导致动作时序精度受限。离散世界模型适合“回合制”环境或固定频率采样环境但很难适应真实物理系统的非均匀时间事件。2.2 把时间变成可查询的连续变量连续时间世界模型的核心变化是把时间当作输入特征。模型不再表示“下一步”而是表示“目标时刻 τ 的状态”s(τ) f_θ(history, actions, τ)其中 history 是过去若干时刻的观测序列actions 是这段过程中执行的动作τ 是相对当前时刻的目标时间。训练时τ 可以在一个连续范围内随机采样模型被迫学会不同时间跨度下的动态变化规律。推理时不管你想输出 10fps、30fps 还是 60fps只需要把 τ 设成对应的时间点。这种设计的本质是让模型学习一个“连续时间函数”而不是一个“离散时间序列生成器”。从函数的角度看离散帧不过是这个连续函数在某些时间点上的取值。2.3 连续时间与扩散模型、流匹配的关系在更复杂的图像和视频生成场景中连续时间建模还和生成模型密切相关。这里有另一个层面的“时间”第一个层面是环境时间 τ也就是世界模型预测的状态时刻。第二个层面是生成过程时间比如扩散模型中的噪声扩散步。扩散模型先把数据逐步加噪变成噪声分布再训练模型去预测噪声。推理时从噪声出发通过多步去噪还原数据。流匹配模型则更直接地把数据分布到噪声分布的过程建模成一条连续路径用神经网络拟合速度场然后通过积分常微分方程ODE从噪声还原数据。这两种方法都天然支持连续时间参数化。如果我们把环境时间 τ 作为额外条件输入扩散模型就可以在生成某个帧时明确告诉模型“我要的是 τ 时刻的帧”而不是让模型隐式地按顺序生成。这也是任意帧率生成在视频扩散模型里可行的原因之一。2.4 为什么能做到任意帧率任意帧率生成的本质是把“时间轴采样”从训练时固定下来变成推理时自由确定。用一句话概括网络学习的是一个关于时间 τ 的函数推理时按目标帧率枚举 τ 即可。假设我们想生成 1 秒内、30fps 的视频那么查询时间序列是times [1/30, 2/30, 3/30, ..., 30/30]如果换成 60fps只需要把时间步长改成 1/60times [1/60, 2/60, 3/60, ..., 60/60]模型结构完全不变。推理时这些查询甚至可以在 batch 维度并行一次推理输出多个时刻的帧效率并不差。3. 技术拆解最小可运行的连续时间模型3.1 整体设计为了把原理讲清楚我先用一个最简单的场景做 demo预测二维平面上的连续运动轨迹。模型接收过去 4 个观测点以及一个目标相对时间 τ输出未来时刻的位置坐标。这个模型虽然不涉及图像但它保留了连续时间世界模型的三个关键点时间以连续数值输入。训练时随机采样 τ覆盖不同时间跨度。推理时按任意帧率枚举 τ得到不同帧率的轨迹。视觉版的连续时间具身世界模型基本结构也是这个思路只是把“二维坐标”换成“图像帧的 latent”把预测网络换成扩散模型或流匹配模型。3.2 时间编码与模型结构Transformer 在做位置编码时常用正弦函数把离散位置变成向量。这里我们把同样的思路用在连续时间上把 τ 编码成高维向量再和观测历史拼接。# model.py import math import torch import torch.nn as nn class SinusoidalTimeEmbedding(nn.Module): 把连续时间 t 编码成向量t 越小越好训练。 def __init__(self, dim64): super().__init__() self.dim dim def forward(self, t): # t: (B,) half self.dim // 2 freqs torch.exp( -math.log(10000.0) * torch.arange(half, devicet.device) / half ) args t.unsqueeze(-1) * freqs return torch.cat([torch.sin(args), torch.cos(args)], dim-1) class ContinuousStateModel(nn.Module): 基于历史观测和时间差预测目标时刻的状态。 def __init__(self, obs_dim2, history_len4, time_dim64, hidden_dim128): super().__init__() self.history_len history_len self.time_embed SinusoidalTimeEmbedding(time_dim) input_dim history_len * obs_dim time_dim self.mlp nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, obs_dim), ) def forward(self, history_obs, delta_t): # history_obs: (B, history_len, obs_dim) # delta_t: (B,) B history_obs.size(0) flat_hist history_obs.reshape(B, -1) t_emb self.time_embed(delta_t) x torch.cat([flat_hist, t_emb], dim-1) return self.mlp(x)这里使用“相对时间差”而不是“绝对时间戳”。原因是模型只需要知道目标时刻相对于当前时刻过去了多久不需要关心全局时间零点。相对时间差在推理时也更直观用户说“要 0.033 秒后的帧”模型直接处理 0.033。使用正弦时间编码有两个好处一是连续时间可以映射成向量便于神经网络处理二是相近的时间差会得到相近的编码模型能平滑插值。3.3 任意帧率采样逻辑有了模型后任意帧率生成就是一个简单的循环# generate_any_fps.py import torch torch.no_grad() def generate_at_target_fps(model, history_obs, fps, duration2.0): history_obs: (history_len, obs_dim) 或 (1, history_len, obs_dim) fps: 目标帧率比如 10、30、60 duration: 生成多少秒的预测 if history_obs.dim() 2: history_obs history_obs.unsqueeze(0) start 1.0 / fps query_times torch.arange(start, duration 1e-6, 1.0 / fps) frames [] for tau in query_times: delta_t tau.unsqueeze(0) # 只预测单条轨迹时为 scalar pred model(history_obs, delta_t) frames.append(pred.squeeze(0).cpu().numpy()) return query_times.numpy(), frames这段代码看起来简单但它就是“任意帧率自由生成”的算法核心把帧率转换成查询时间序列然后在连续时间函数上取点。如果生成多条轨迹还可以把多个 τ 组成 batch一次前向并行输出。实际部署时建议分批处理提高吞吐而不是一个时刻一个时刻地循环。3.4 从状态模型扩展到图像与视频生成上面模型输出的是 2D 坐标只能演示原理。真正做连续时间视频或具身世界模型时我们需要把“二维坐标预测”替换成“图像帧条件生成”。一个比较务实的做法是把扩散模型作为帧生成器环境时间 τ 作为条件输入。整体接口可以写成# conditional_diffusion_generator.py # 这是一个伪接口演示连续时间视频生成的模块划分。 import torch class ContinuousTimeDiffusionGenerator: 真实实现中model 可以是一个 U-Net / DiT / 3D VAE 的条件扩散模型。 这里重点展示“查询时间点”的组织方式。 def __init__(self, model, tokenizer): self.model model self.tokenizer tokenizer torch.no_grad() def generate_frame_at(self, context, tau, diffusion_steps50): # 1. 从纯噪声开始 z torch.randn(1, 4, 32, 32) # 2. 按扩散模型采样流程逐步去噪 # 每步把 tau 作为条件告诉模型现在要生成第 tau 时刻的帧 for step in range(diffusion_steps): noise_pred self.model(z, step, context, tau) z z - noise_pred * 0.1 # 3. 解码成图像 return self.tokenizer.decode(z) torch.no_grad() def generate_video(self, context, start_t, end_t, fps): frames [] t start_t while t end_t: frames.append(self.generate_frame_at(context, torch.tensor([t]))) t 1.0 / fps return torch.stack(frames)为什么要用扩散模型而不是直接回归图像因为图像分布非常复杂直接回归容易出现模糊、鬼影和细节丢失。扩散模型把生成问题转化为“从噪声逐步细化”的过程能生成更锐利的视频帧。流匹配模型则通过拟合连续速度场用更少的采样步达到类似效果。4. 完整实战以任意帧率生成二维运动轨迹下面用一个完整可运行的例子演示连续时间世界模型的训练和推理。4.1 数据构造我使用正弦余弦组合出的连续轨迹这样任何时刻的位置都有解析解可以随机采样任意 τ而不受离散网格限制。# data_utils.py import numpy as np import torch def traj_at(t, phase): 给定时间点 t 和随机相位 phase返回二维位置。 t: (S,) 或 (B,) phase: (B,) x np.sin(t phase[:, None]) y np.cos(t phase[:, None]) return np.stack([x, y], axis-1) def get_batch(batch_size256, history_len4, dt0.1, max_delta2.0): 返回: history_obs: (B, history_len, 2) delta_t: (B,) target: (B, 2) phase np.random.uniform(0, 2 * np.pi, size(batch_size,)) # 历史时刻取负时间表示过去 hist_t np.arange(-(history_len - 1), 1) * dt history_obs traj_at(hist_t, phase) # 目标时间差在 [0, max_delta] 内连续采样 delta_t np.random.uniform(0.0, max_delta, size(batch_size,)) target np.sin(delta_t phase) target np.stack([target, np.cos(delta_t phase)], axis-1) return ( torch.tensor(history_obs, dtypetorch.float32), torch.tensor(delta_t, dtypetorch.float32), torch.tensor(target, dtypetorch.float32), )这里有两个细节值得注意历史观测的时间间隔可以固定也可以随机。固定间隔便于演示随机间隔能让模型对不均匀采样更鲁棒。delta_t 不是取固定值而是连续随机采样。这样模型见到的是不同时间跨度推理时遇到任意帧率才不会“没见过”。如果换成真实传感器数据delta_t 可能对应着动作执行时长、传感器采样间隔甚至非均匀等待时间逻辑是一样的随机时间采样让模型学习连续函数。4.2 训练循环训练逻辑很简单预测目标位置计算 MSE 损失。# train.py import torch import torch.nn as nn from data_utils import get_batch from model import ContinuousStateModel def main(): device torch.device(cuda if torch.cuda.is_available() else cpu) model ContinuousStateModel(obs_dim2, history_len4).to(device) optimizer torch.optim.AdamW(model.parameters(), lr1e-3) loss_fn nn.MSELoss() steps 3000 for step in range(steps): history_obs, delta_t, target get_batch(batch_size256) history_obs history_obs.to(device) delta_t delta_t.to(device) target target.to(device) pred model(history_obs, delta_t) loss loss_fn(pred, target) optimizer.zero_grad() loss.backward() optimizer.step() if step % 500 0: print(fstep {step}, loss {loss.item():.6f}) if __name__ __main__: main()训练 3000 步通常已经足够让这个简单模型学到基本轨迹规律。如果你的数据轨迹更复杂可以增大 hidden_dim、加深 MLP或者换用带时序结构的编码器。这里选择 MLP 是为了让学习重点集中在“连续时间命中”而不是网络结构上。4.3 推理与帧率切换训练完成后我们用同一个模型分别以 10fps、30fps、60fps 生成预测轨迹。# inference.py import numpy as np import torch from data_utils import traj_at from model import ContinuousStateModel def load_model(): model ContinuousStateModel(obs_dim2, history_len4) # 实际项目中应加载训练好的权重 model.load_state_dict(torch.load(model.pth)) model.eval() return model def generate(model, fps, duration2.0): phase 0.6 hist_t np.arange(-3, 1) * 0.1 history_obs traj_at(hist_t, np.array([phase])) # (1, 4, 2) history_tensor torch.tensor(history_obs, dtypetorch.float32) query_times np.arange(1.0 / fps, duration 1e-6, 1.0 / fps) frames [] with torch.no_grad(): for tau in query_times: delta_t torch.tensor([tau], dtypetorch.float32) pred model(history_tensor, delta_t) frames.append(pred.squeeze(0).numpy()) return query_times, np.array(frames) if __name__ __main__: model load_model() for fps in [10, 30, 60]: times, frames generate(model, fps) print(ffps{fps}, generated {len(frames)} frames) print(ffirst frame: {frames[0]}, last frame: {frames[-1]})输出类似fps10, generated 20 frames first frame: [0.324, 0.946], last frame: [1.180, -0.459] fps30, generated 60 frames first frame: [0.324, 0.946], last frame: [1.180, -0.459] fps60, generated 120 frames first frame: [0.324, 0.946], last frame: [1.180, -0.459]相同时间跨度的首尾帧相近符合预期。区别在于中间帧密度不同60fps 在相邻两帧之间插入了更细的位置。4.4 运行效果与观察点跑完这个 demo可以重点观察三件事预测序列是否连续。如果相邻帧之间出现跳变说明模型对连续时间的拟合还不够好可以增大训练步数或提高网络容量。不同帧率下的轨迹是否一致。同一个物理过程在 10fps 采样和 60fps 采样下趋势应该相同只是采样密度不同。外推时间范围是否可用。训练时 max_delta2.0推理时查询 2.5 秒意味着时间超出训练范围属于外推。MLP 外推能力有限这也是工程落地中最容易出现问题的点。5. 常见问题与排查思路5.1 问题速查表问题现象常见原因解决思路生成画面或轨迹抖动不连续训练时没有随机时间采样或模型容量不足检查时间采样范围增大网络容量10fps 结果好60fps 结果差训练数据本身只有低帧率模型见过的高频细节太少提高训练数据采样率或在连续轨迹上插值增样本外推 2 秒后结果明显发散查询时间超出训练范围神经网络外推能力弱限制推理时间范围或把时间输入做归一化处理动作条件没有起作用动作信息注入方式弱改用交叉注意力或显式拼接并检查动作维度和时间戳对齐视频生成出现鬼影扩散模型迭代步数不足或时域一致性约束太弱增大采样步数加入时序损失或时序判别器训练时 loss 不降时间编码尺度不适合检查 delta_t 是否过大尝试除以缩放因子模型输出状态和实际物理规律不符数据本身缺传感器同步信息检查数据管线的时间戳统一数据时钟5.2 三个需要重点排查的方向第一时间范围外推。很多连续时间模型在训练区间内部表现良好一旦查询时间超出训练范围就开始发散。工程上最稳妥的做法是限制推理时间段或者把时间输入除以一个常数归一化到合理范围。如果必须支持长时预测可以考虑递归预测每次只预测较短时间段。第二条件注入方式。连续时间只是模型的一个输入历史观测和动作同样重要。如果动作信息只是简单拼接模型可能学会忽略它。在视频扩散模型中建议用交叉注意力让每个时间点都能聚焦到相关历史信息。第三评估指标。不要只盯着生成图像的清晰度。对具身世界模型而言状态预测的误差、动作执行成功率、时间对齐精度可能更重要。比如机器人预测“2.0 秒时手应该到 A 点”这个误差如果大于 5cm说明模型的连续时间建模还不够准。6. 工程落地与最佳实践6.1 数据与时间戳连续时间世界模型对数据质量的要求比离散模型更高。离散模型即使时间戳有一点波动也常被当作固定间隔处理连续模型则会把时间差作为输入如果时间戳错误模型会被迫学习噪声。落地的关键在于使用统一时钟同步多传感器数据。记录每个样本的真实采集时间戳不要只记录下标。训练时可以对时间戳做小噪声扰动增强模型对时间抖动容忍度。数据集中时间范围要覆盖推理时可能遇到的帧率范围。6.2 模型与训练不要一开始就尝试大规模视频生成。建议先在低维状态或中小分辨率视频上验证连续时间建模是否有效再逐步扩大数据规模。训练时优先做随机时间采样。如果数据来自固定 30fps 视频可以在相邻帧之间做插值生成更高帧率的监督目标让模型学会任意时间查询。对于图像级生成可以用扩散模型或流匹配模型但生成网络本身不是重点重点是把时间 τ 作为条件贯穿到整个采样过程中。另外要注意训练时间范围。建议把 delta_t 的上限设置成略大于实际推理需求但不要盲目设得很大。范围过大会让模型浪费容量在很少出现的长时预测上反而影响短时预测精度。6.3 推理与部署推理阶段任意帧率生成很容易实现但要注意吞吐量。如果一帧一帧循环生成 120 帧会调用 120 次模型前向耗时较长。可以把多个查询时间点组成 batch并行生成。对于强化学习或机器人控制场景实时性要求较高。可以考虑使用 latent space 模型避免直接解码每一帧图像。缓存历史观测的编码结果减少重复计算。对时间轴分层先粗粒度预测关键帧再在关键帧之间并行补帧。6.4 安全边界与评估具身世界模型本质上是预测器预测结果不能直接作为无约束控制的依据。真实机器人上使用这类模型时至少要设置安全和回退机制所有生成的控制指令需要经过安全校验。生产环境变更前先在仿真环境验证再小范围灰度测试。评估指标建议分层次状态预测误差MSE、MAE。视频生成质量FVD、LPIPS。时序精度不同帧率下同一物理过程的轨迹一致性。任务成功率机器人在真实或仿真环境中用模型预测结果做控制后是否完成任务。不要只报告生成视频“看起来真实”还要验证“预测是否足够准”。7. 总结与下一步连续时间具身世界模型的核心思路是把时间从离散索引变成可查询的连续变量并用一个参数化的连续函数表示“给定历史和动作后任意时刻的状态”。任意帧率自由生成只是这个连续函数在时间轴上按需取点而已并不需要为每种帧率单独训练模型。我在跑最小 demo 时最明显的感受是连续时间并不是简单地把时间戳塞进网络就能见效。真正需要改变的是数据管线和训练策略尤其是随机时间采样、时间范围设计、推理时的时间归一化。这些细节决定了模型能否从“能拟合训练点”变成“真正学会了时间的连续性”。如果你也想在自己的项目里尝试我建议按照本文第 4 节的流程先做一个二维轨迹预测把连续时间模型跑通再结合扩散模型扩展到视频 latent。等你把状态预测换成图像帧生成并且用上机器人动作条件后就能体会到这套思路在具身智能场景里的真正价值了。希望这篇笔记对你有用欢迎收藏备用也欢迎在实际复现中多交流。