25FPS、无限时长——Vidu S1 实时视频通话,可与“任何对象”沟通
如果你还停留在"数字人 = 口播播报 + 对口型"的印象里,Vidu S1 会让你重新定义这个词。
Vidu S1,官方给出的定位很直接:"全球最先进的实时 AI 交互模型"。它不是又一个语音驱动口型同步(Lip Sync)工具,而是把实时行为生成塞进了视频生成模型里——数字人能听懂你说什么、理解上下文情绪,并且用连贯的表情、动作、语气实时回应你,而这一切是在 540P/25FPS(最高 42FPS)的视频流里"现场生成"出来的,理论上可以不间断跑上几个小时不崩、不掉线、不降质。

一、技术分析:从"合成视频"到"实时生成视频"
1.1 这不是传统数字人管线
传统数字人技术栈通常是这样一条链路:
文本/语音输入 → TTS 语音合成 → 驱动信号(blendshape/关键点) →
渲染引擎(2D变形 or 3D绑定) → 视频帧输出
这套管线的问题很明显:驱动信号和渲染是分离的,动作库是预设的,模型本质上是在"贴合"一段已经生成好的音频,做的是唇形对齐而不是行为生成。角色不会"思考"该做什么表情,它只会对口型。
Vidu S1 走的是另一条路——流式视频生成模型(Streaming Video Diffusion / Autoregressive Generation)。根据官方描述,它的核心能力是"双向感知":模型同时接收用户的语音、画面(摄像头)输入,理解语义和情绪后,逐帧自回归地生成角色的下一步表现,而不是先规划好一段动作再渲染。这意味着:
-
角色的反应是生成式的,而非从动作库里"调取"的;
-
理论上可以对任意 persona 设定(人设 Prompt)做出符合性格的反应,而不需要为每个角色单独训练动作绑定;
-
音画同步不再是后处理的对齐问题,而是生成过程本身的一部分。

1.2 无限时长生成的关键:不是"长视频",是"流"
官方特别强调"全球首个支持无限互动时长、生成 1 分钟到 2 小时都不掉质量"的能力。这里的技术难点在于,主流视频扩散模型(无论是 Sora 类的全局去噪,还是分块自回归)都存在误差累积问题:生成时间越长,画面越容易漂移、崩坏、色彩偏移。
要做到"无限时长不掉质量",通常需要在以下几个方向做工程与算法上的取舍(这是行业内做流式视频生成的共性思路,Vidu 未必公开全部细节,但从产品行为可以反推):
- 短窗口自回归 + 状态锚定
:不对整段历史做全局注意力,而是维持一个有限窗口的历史帧 + 一个保持角色一致性的"锚点"表征(类似于身份/外观的隐向量),避免长期漂移;
- 误差反馈抑制
:对自回归模型来说,每一步生成都会引入微小误差,如果不加处理会像滚雪球一样放大。工业级方案通常会引入自蒸馏、噪声调度调整或者周期性的"参考帧"校正来抑制这种漂移;
- 推理侧的流水线并行
:540P@25FPS 意味着每 40ms 要吐出一帧,这对推理延迟提出了硬性要求,大概率用了模型蒸馏(把多步去噪蒸馏成少步甚至一步)+ 硬件流水线并行来压低单帧延迟。
这也是为什么 Vidu S1 目前的分辨率停留在 540P——在"实时"和"画质"之间,工程上必须先保证前者,这与 Sora、Veo 这类离线生成模型的技术路线取舍完全不同:那些模型可以用几十秒到几分钟换一段高清视频,Vidu S1 要用几十毫秒换一帧能连续播放的视频。

1.3 系统架构:为什么不是单纯调一个"生成 API"
从 API 文档能看出,Vidu S1 的工程架构其实是三通道分离的:

这个设计思路值得单独说一下:为什么生成出来的视频流不直接走 WebSocket 或 HTTP,而要接一个独立的 RTC SDK?
原因很直接——视频流的实时传输是一个已经被高度优化的基础设施问题(弱网对抗、丢包重传、自适应码率、NAT 穿透),没有必要在生成模型的服务里重新造轮子。Vidu 把"生成"和"传输"解耦:模型侧只负责尽快吐出音视频帧,AliRTC 负责把这些帧稳定地送到用户端。这也是目前几乎所有实时数字人/实时对话式 AI 产品(包括 Realtime API 类产品)的通用架构选择。
代价是接入复杂度上升——开发者需要同时维护 HTTP 会话状态、WebSocket 信令状态、RTC 连接状态三条线,这也是下一节要重点解决的问题。

二、代码实现:从零跑通一次 Vidu S1 会话
官方文档把整个流程定义为 6 步,这里给出一份可以直接改造使用的完整实现,分成"创建会话(Python)"和"信令与音视频(浏览器端 JS)"两部分。
2.1 Step 1:创建数字人会话(Python)
import requests
API_KEY = "vda_your_api_key_here"
HOST = "api.vidu.com" # 国际站;国内请求用 api.vidu.cn
def create_live_session(image_uri: str, persona: str, name: str = "Mia",
voice: str = "", call_mode: str = "video"):
"""
创建一个 Vidu S1 实时数字人会话
call_mode: "video" (音频+视频) 或 "audio" (纯语音)
"""
url = f"https://{HOST}/live/v1/lives"
headers = {
"Authorization": f"Token {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"call_mode": call_mode,
"avatar": {
"persona": persona,
"image_uri": image_uri,
"name": name,
"voice": voice, # 留空使用默认音色 Tina
},
}
resp = requests.post(url, json=payload, headers=headers, timeout=10)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
result = create_live_session(
image_uri="https://your-cdn.com/avatar.png",
persona=(
"你是一位热情、专业的客服助手,说话简洁友好,"
"遇到用户情绪低落时会主动安抚,回答尽量控制在两句话以内。"
),
name="小V",
)
print("live_id:", result["live"]["id"])
print("rtc_token:", result["rtc"]["token"])
print("rtc_user_id:", result["rtc"]["user_id"])
拿到 live.id(后面信令要用)和 rtc 字段(加入实时音视频房间要用)之后,注意几个容易踩坑的细节:
-
live.status 此时是 waiting,房间已创建但角色还没"上线",不能直接以为可以通话了;
-
live_duration 单次会话最长 600 秒(10 分钟),到时间会被服务端强制断开——这不等于官方宣传的"无限时长"矛盾,无限时长指的是单次生成不会因模型误差累积而降质,实际产品层面的会话时长限制是工程/计费层面的策略,如果需要更长的连续对话,需要在客户端做会话续期(新建 session 无缝切换)。

2.2 Step 2-4:加入 RTC 频道 + WebSocket 信令(浏览器端)
// 假设已经通过后端拿到了 Step1 返回的 live 和 rtc 对象
async function startViduSession(live, rtc, apiKey) {
// ---- Step 2: 加入 AliRTC 频道 ----
const aliRtc = new AliRTCEngine(); // 需引入 AliRTC SDK
await aliRtc.joinChannel(rtc.token, rtc.user_id);
await aliRtc.publishLocalAudioStream(true); // 打开麦克风
await aliRtc.publishLocalVideoStream(true); // 打开摄像头(video 模式必须)
aliRtc.on('videoSubscribeStateChanged', (uid, newState) => {
// 数字人的 uid 格式固定为 live-bot-{creatorID}-{liveID}
if (newState === 'subscribed' && uid.startsWith('live-bot-')) {
renderRemoteVideo(uid); // 把数字人的视频流渲染到页面
}
});
// ---- Step 3+4: 建立 WebSocket 控制通道,带指数退避重连 ----
connectSignaling(live.id, apiKey);
}
function connectSignaling(liveId, apiKey, attempt = 0) {
const wsUrl =
`wss://api.vidu.com/live/ws/live/connect` +
`?live_id=${liveId}&authorization=${encodeURIComponent('Token ' + apiKey)}`;
const ws = new WebSocket(wsUrl);
ws.onopen = () => {
ws.send(JSON.stringify({
type: 1,
live_id: liveId,
seq_id: 1,
payload: { conn_init: { version: 1 } },
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
// type 2: 初始化响应
if (msg.type === 2) {
const ack = msg.payload.conn_init_ack;
if (ack.success) {
console.log('数字人已就绪,会话正式开始(计费从此刻启动)');
} else if (ack.error_code === 'NOT_READY') {
// 视频模式下常见,指数退避重连:2s -> 4s -> 8s
const delay = Math.min(2000 * 2 ** attempt, 8000);
ws.close();
setTimeout(() => connectSignaling(liveId, apiKey, attempt + 1), delay);
} else if (ack.error_code === 'LIVE_CONN_INIT_FAILED') {
console.error('初始化永久失败,需要重新创建 session');
}
}
// type 6: 服务端强制断开
if (msg.type === 6) {
const reason = msg.payload.hangup.hangup_reason;
handleHangup(reason); // 根据 reason 做不同的用户提示与重连策略
}
};
ws.onclose = () => {
console.warn('WebSocket 连接已关闭');
};
}
function handleHangup(reason) {
const reasonMap = {
user_end: '用户主动挂断',
timeout: '会话超时',
audit_violation: '内容审核未通过',
credit_insufficient: '账户余额不足',
};
console.log(reasonMap[reason] || `会话结束: ${reason}`);
}
几个工程上必须处理的细节,官方文档专门强调了,很容易被忽视:
- NOT_READY 是视频模式下的正常现象
,不是错误,必须做指数退避重连,而不是直接报错给用户;
- 心跳
:服务端每 5 秒 ping 一次,客户端 15 秒内没有响应会被判定为掉线,大多数 WebSocket 库默认已经处理 ping/pong,但用原生浏览器 WebSocket API 时要确认没有手动禁用;
- 计费起点是 conn_init_ack.success = true 那一刻
,也就是说创建 session、等待角色准备的时间不计费,这对做成本控制很重要。

2.3 Step 5-6:挂断与账单查询
function endSession(ws, aliRtc, liveId) {
ws.send(JSON.stringify({
type: 5,
live_id: liveId,
seq_id: 2,
payload: { hangup: { hangup_reason: 'user_end' } },
}));
ws.close();
aliRtc.leaveChannel();
}
def get_session_bill(live_id: str):
url = f"https://{HOST}/live/v1/lives/{live_id}"
headers = {"Authorization": f"Token {API_KEY}"}
resp = requests.get(url, headers=headers, timeout=10)
resp.raise_for_status()
data = resp.json()
print(f"计费时长: {data['billed_seconds']} 秒, 状态: {data['status']}")
return data
按官方定价,3 credits / 2 秒,且每 45 credits 起充才能建会话,折算下来大约 0.0469 credits/秒,实际成本要结合官方 credit 单价(0.03125)自己核算——如果打算做 To C 产品,这一块的实时成本核算不能省。
三、前沿总结:实时数字人赛道走到哪一步了
把 Vidu S1 放进整个赛道里看,会更清楚它的定位:
对比语音驱动数字人(如传统 D-ID、HeyGen 类工具):这类产品本质是"TTS + 驱动模型",交互是回合制的——你说完一句,等它生成一段回复视频。Vidu S1 主打的是"持续在线、随时可打断、连续反应"的流式交互,这才是它和市面上大多数"数字人生成工具"的本质区别。
对比实时语音助手(如 GPT-4o 语音模式、各类 Realtime API):那些产品解决的是"实时语音对话",输出是声音;Vidu S1 解决的是"实时视频对话",输出是一个会做表情、有肢体反应的活人形象。可以理解为在实时语音交互之上,多加了一层"视觉具身"。这个方向如果做得好,客服、陪伴、虚拟主播、教育讲解这些场景的体验会有质的提升——用户面对的不再是一个说话的头像,而是一个"看起来在认真听你说话"的角色。
当前的技术边界也很明显:
-
540P 的分辨率决定了它现阶段更适合手机端小窗口、聊天气泡类场景,还不足以撑起大屏或商用直播的画质要求;
-
单次会话 10 分钟的硬性上限,说明"无限时长"目前更多是模型能力层面的验证,产品化的长连接体验还需要客户端做会话拼接;
-
依赖 AliRTC 这样的第三方实时传输基础设施,意味着整体延迟和稳定性会受网络基础设施影响,不是纯模型侧能完全掌控的变量;
-
声音克隆、多角色人设这些能力目前更偏向"配置化",人设的深度记忆(长期记忆而非官方说的"短期记忆")还没有解决,这也是所有陪伴类数字人产品共同面对的下一道坎。
往前看,实时交互视频生成大概率会朝三个方向继续演化:分辨率和帧率的进一步提升(跟推理成本对抗)、多模态输入理解的加深(不只是听懂语音,还要"看懂"用户表情和场景)、以及长期记忆机制的引入(让角色真正"记住你是谁"而不是每次会话都是一次性人格)。Vidu S1 目前展示的是流式生成本身可行,接下来比拼的会是谁能把这套技术在成本、画质、记忆深度之间找到更好的平衡点。
更多transformer,VIT,swin tranformer
参考头条号:人工智能研究所
v号:人工智能研究Suo, 启示AI科技
动画详解transformer 在线视频教程


DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)