For the complete documentation index, see llms.txt. This page is also available as Markdown.

口型同步与 Blendshape

使用与机器人音频一并流式传输的 blendshape 数据,为 3D 角色驱动实时面部动画。

工作原理

  1. 在配置中启用唇形同步 —— 服务器会在生成 TTS 音频的同时开始生成 blendshape 帧。

  2. 帧会以 10 帧为一批到达,并缓冲到 client.blendshapeQueue.

  3. 你的渲染循环以 60 fps 从队列中读取帧,并与机器人说话时同步。

  4. 当机器人停止说话时,队列会清空并发出对话结束信号。


启用唇形同步

const client = useConvaiClient({
  apiKey: '...',
  characterId: '...',
  enableLipsync: true,
  blendshapeConfig: {
    format: 'arkit', // 或 'mha'(MetaHuman 251,默认)
  },
});

格式(由服务器验证 — 传入未知字符串会被拒绝连接,并返回有效列表):

格式

帧维度

通道命名

备注

"mha" (默认)

251

CTRL_expressions_*

Unreal MetaHuman Animation;MetaHuman-Lite 角色(103 个形变)会从同一流中使用其命名子集

"arkit"

61

ARKit 名称(JawOpen,…)

Apple ARKit 标准

"cc4_extended"

170

CC4 ExpressionPlus

Reallusion Character Creator 4

"cc5_hd"

服务器接受,但目前输出 没有帧

"visemes"

15

OVR viseme 集

sil, PP, FF, TH, DD, kk, CH, SS, nn, RR, aa, E, ih, oh, ou


在渲染循环中读取帧

访问 client.blendshapeQueue 从你的动画循环中访问。队列以 60 fps 进行时间索引。

getFrameAtTime(elapsedSeconds)

返回最接近给定经过时间的帧(假设 60 fps),或者 null 如果队列为空。

getFrameWithAlpha(index)

getFrame 相同,但会自动应用淡入(前 10 帧)和淡出(最后 10 帧或被中断时):


将 blendshape 应用到 Three.js 网格

ARKIT_ORDER_61 是一个有序数组,包含 61 个与帧索引相匹配的 ARKit blendshape 名称。

对于 MetaHuman("mha" 格式),请改为导入 METAHUMAN_ORDER_251


自定义映射器

使用自定义映射器将传入的 blendshape 转换为与你角色的 morph target 名称匹配。

ARKit 名称映射器

映射器会在每一帧进入队列时应用。

直接名称映射的角色(无需映射器)

如果你角色的 morph target 名称 完全 与流的通道名称一致,那么就完全跳过映射器,并按名称写入帧:

  • format: 'mha' 通道命名为 CTRL_expressions_jawOpen, CTRL_expressions_eyeBlinkL,… — 与 MetaHuman 风格导出相匹配。

  • format: 'arkit' 通道使用 ARKit 名称(JawOpen, EyeBlinkLeft,…)。

每个网格只构建一次索引表,然后以零每帧查找的方式应用帧:

导出有时会把名称弄乱(例如缺少分隔符: CTRL_expressionsjawOpen)。在加载时规范化 morphTargetDictionary 的键,而不是调整每个使用者。

连接后设置映射器


BlendshapeQueue API

client.blendshapeQueue 是实时队列实例。

状态检查

帧访问

消费

回合统计

中断

调试


让唇形同步更自然

在生产角色上验证过的模式——每一种都针对你否则会看到的特定瑕疵:

让流淡入淡出

原始帧在第一帧时会以满强度冲到脸上,而在帧停止时会冻结最后一个 viseme。将每个由流驱动的值乘以一个平滑包络:在语音开始时约 0.25 秒内渐强,在最后一帧后约 0.5 秒内渐弱(保留最后一帧并将其淡到 0——不要在半途中丢弃)。

(getFrameWithAlpha 如果你直接消费队列,这会自动完成;如果你自己缓冲/应用帧,请应用自己的包络。)

让程序系统拥有自己的通道

如果你运行程序化眨眼或随镜头跟随的视线,流必须 绝不能写入眼睛通道 —— 两个使用不同定时器的写入者会彼此竞争并导致闪烁(眨眼甚至不会明显闭合)。保留一份流应保持不动的通道索引跳过掩码,并让你的眨眼/视线代码完全拥有它们。

语音结束检测

帧可能会在任何显式结束事件之前停止到达。将大约 300 毫秒内没有新帧视为语音结束并开始淡出——这样官方结束信号即使稍后到达,也不会出现可见冻结。

按通道增益

流是为参考脸型调校的;你角色的形状可能会显得过强。按通道的增益表可以精准修正这一点——例如在一个 MetaHuman 风格的绑定上,我们会设置 jawOpen × 0.7 以及横向的下颌/嘴部位移 × 0(它们会显得歪斜),其余全部保持 1。

嘴部对称性

如果流对 L/R 嘴部对称通道的驱动不均衡(我们测到左右最多可差 1.5×),在应用前对每一对侧向通道取平均(…L/…R)——张开的嘴看起来会对称得多。

在动画混合器之后应用

如果身体动画片段也会影响头部,请在 之后 混合器每个渲染帧更新后,重新应用当前唇形同步帧,这样说话始终在脸部上占优。


缓冲调优

frames_buffer_duration 选项控制服务器在连同音频一起释放之前累积多少秒的 blendshape。更高的值会提升唇形同步精度,但会增加延迟。

最后更新于

这有帮助吗?