放大
2.0×
|
上下位移
5%
放大的是渲染面本身(缓冲跟着变大),不是拉伸位图 —— 放大后仍然清晰。
shapeV2 口型(点击 → 三个 riv 同时切到该 Mouths_Talk)
键盘 ← → 可顺序切换口型
实测:三个 riv 的 32 个
Mouth value_* 输入默认值都是 100(不是 0),
SDK 只写「当前形状」那一个、把「上一个形状」归零。但只有当前
Mouths_Talk 对应的那一路影响画面——其余输入停在 100 还是写 0,
画面完全一致(2026-08-06 截图逐像素比对)。所以「写 0」只是让读值干净,
不改变观感。当前形状的 value 才是开口大小的主驱动:0=闭嘴,100=大张。
浮点口型强度(Mouth value_*)
|
开口值
100
这个数直接写进
Mouth value_<当前形状>(0=闭嘴,100=满开),关掉开关则不写、纯枚举姿态。
线上(2026-08-07 起)所有中文口型统一用后台那一个强度值,不再按音素规则值分层 ——
区分交给 shapeV2 姿态本身;只有 p/b/m 闭唇帧恒为 0。真实序列去第二个 tab 看。
请求 core(真实 socket.io + TTS,noGenerateResponse 纯直读,不走 LLM)
endpoint
path
provider
|
apiKey
线上默认 dev:REST / ArticuLM 由后端自动鉴权
请求参数 ·
裁剪档 mode
|
口型强度
100
admin passkey
改动自动存 localStorage
⚠️ core 的 TTS 缓存(仅
ENABLE_CACHE=true 时启用)key 含裁剪档(本次发版(含英文裁剪档)起);
更早版本不含,切档后同一句话会命中旧缓存。想确定看到真实效果可勾「绕过缓存」或换一句新文本。
裁剪档只随 REST 请求 / 查看 curl 以
mode 字段发出,不改后台;socket 路线不支持请求级覆盖,仍按后台设置。
viseme 序列
| # | 字 | shapeV2 | Talk | 音素 | value | 起–止 % | 时长 |
|---|---|---|---|---|---|---|---|
| 尚未请求 | |||||||
播放
style
口型对照表 · 龙虾小女孩 Mouths style=1
(headless chrome 实截,非手绘;换 riv 后跑 node gen-mouth-chart.mjs 重生成)
逐字口型表(离线预算,数据出自 core 管线;点字 → 右侧定住该帧)
中文裁剪档
|
口型强度
100
|
存的是规则值;线上已改为统一强度(非零规则值一律换成上方那个值,只有 0/null 保留),
所以规则值现在只用来分类闭唇帧。滑块现算,改了不用重新生成数据。
帧序列与裁剪由 core 的
annotateMouthValues / simplifyChineseVisemes 真跑,非前端重实现。
键盘 ← → 切字,↑ ↓ 切帧。
加载中…
未选字
ArticuLM 对照 规则管线 vs 口型模型,逐帧并排
走
线上默认 dev 环境由后端自动鉴权,无需填写 passkey。其他环境沿用 Tab 2 的连接配置。
POST /api/tts/visemes(真合成一次、不走缓存)拿到音素帧,由 core 在同一次请求内调用模型,返回 shapeV2 + strength,按下标并排。
对照的主角是强度:实测中文 shapeV2 两侧零差异(模型复现的就是
IPA_DUOLINGO_ZH),而规则侧的浮点值被 remapMouthValue
压成一个全局常量,模型侧每音素有区分。线上默认 dev 环境由后端自动鉴权,无需填写 passkey。其他环境沿用 Tab 2 的连接配置。
音素由接口生成;修改模型模式后重新请求。阿拉伯语自动使用专用模型接口。
(当前:ArticuLM)
逐帧对照
| # | 字 | shapeV2 | Talk | 强度 | 规则 | 音素 | 起–止 % | 时长 |
|---|---|---|---|---|---|---|---|---|
| 尚未请求 | ||||||||
播放
style
词级嘴形表(按词整体替换该词跨度的帧;未命中的字仍走逐字规则)
中文裁剪档
|
|
未保存
endpoint 与 admin passkey 沿用 tab 2。词表的唯一真源是 R2 上的一个对象 ——
dev 和 persona 读的是同一份,保存后线上立即生效(没有灰度);服务端每次写前自动备份改动前的整表,可回滚。
存的是最终下发值(0-100 或
—=不写浮点,0=闭唇),运行时不再过 remapMouthValue。
每档一套帧,帧组数必须等于字数(音频按字给时间片)—— 一个字下的帧数就是可调的自由度。
新词的种子必须由 core 管线产出:在本目录跑 node gen-zh-words.mjs --only 新词(词先加进 zh-word-seed.js),
生成的仓库 JSON 只是首装种子 + 兜底,进 git 之后要在这里把新词保存到 R2 才会生效。
未载入
未选词