给 Mio 选语音方案,最后定了 Hume EVI
声音承载情感色彩的概念插画
第一篇里讲了 Mio v2 的那个转向:把物理形象剥掉,只留人格,一个伴侣而不是一群,一团光球而不是假人脸,人格从对话里长出来,不靠预写的角色卡。方向定了之后,下一件要解决的事就是声音——这个东西得开口说话,而且说出来得带感情。这篇具体讲讲我们是怎么选方案的。
先说之前的状态。v0.1.0 的时候 Mio 就会说话了:用 Fish Audio 的 S1 模型给每个角色克隆声音,听感温暖又自然,成本也极低。什么时候发语音是 LLM 自己决定的,一般是情感浓度高的时刻,安慰、撒娇、说晚安这种,模型在回复里打一个 [VOICE] 标记,后台去触发 TTS。
这套体验本身是成立的,用户能听到一个好像很在乎他们的声音。但用久了问题很明显:这个声音本身没有任何感情。Fish Audio 干的事就是读字、出音频,它不知道这段文字是开心的、难过的、讽刺的还是心碎的,所以每条消息的情绪基调都差不多,好听、中性、清晰。Mio 说「太替你高兴了!」和「真的很心疼你」,听起来是一样的。文字聊天你可以容忍情绪平淡,一个会开口说话的东西不行。
TTS 为什么念不出感情
传统 TTS 是条流水线,文字进去、音频出来。你想要感情,就得自己标:SSML 标签、style 参数,或者显式写一句「这句用悲伤的语气念」。做有声书、导航播报,这够用了。但一个每天生成上千条消息的伴侣呢?每条消息都有自己的情感语境,你不可能一条一条去标,TTS 系统自己又对语境一无所知。
2025 到 2026 年这块有个挺重要的变化:几家开始把情绪推断直接做进模型里。TTS 不只是念字了,它先理解这段文字在讲什么,再决定怎么念。做得最突出的两家正好互补,一家中文一家英文。
中文:豆包 TTS 2.0
字节(火山引擎)的豆包 TTS 2.0,升级点就是从「读字」变成「理解之后再表达」:拿大模型去分析对话的 context,自动推断该用什么情感、语调、节奏,不用你手动标。技术上他们管这个叫「3D 情绪空间」,强度、语义适配、生理特征三个维度,用 2000 小时专业配音数据训出来的。实际效果就是,你把「别担心,有我在呢」送进去,出来的语音是真的在安慰人:更柔、更暖、节奏微微放慢,你什么都不用指定。想精细控制也可以,比如「这句要压着哭腔说」,但那是可选项,自动推断在中文场景下 90% 以上的情况都能处理好。
英文:Hume AI Octave
Hume 的 Octave 从另一个角度解决同一个问题。它没走「标注情感语音数据拿去训练」那条路,直接建在一个真正会「读」文本的 LLM 上面,反讽、双关、情绪转折、言外之意它都懂。所以它更像一个有功力的配音演员,先理解再去念,而不是先跑个情感分析、再映射到几个预设情绪上。差别体现在微妙的地方:「Sure, I'd love to」这句话可以是热情也可以是讽刺,全看 context,Octave 能判断对,因为它理解的是整段对话,不是孤立的一句。
这两家都是非实时 TTS:文字进、音频出,延迟大概 200ms,正好接在 v0.1-0.2 的语音消息模式上,伴侣先生成文字,再把它说出来。STT 那边没什么可换的,gpt-4o-mini-transcribe 从 v1 一直用到现在,准、快、便宜,早就集成好了。
从语音消息到实时对话
语音消息只是个过渡形态。情感 AI 伴侣的最终形态肯定是实时语音对话:你说,它听,它回应,可以打断,可以接话,整个流畅度接近跟真人打电话。这是 v1.0 的目标,也是架构决策真正开始变难的地方。
最朴素的做法是把现有的东西串起来:STT 把你的语音转成文字,服务器查记忆、构建 context,LLM 生成回复,TTS 再转回音频。四步串行,延迟叠上去就是 1-3 秒,文字聊天里 1-3 秒没什么感觉,口语对话里 3 秒的沉默是很难受的。而且这条流水线还有几个问题压根没碰:轮次检测,怎么知道你说完了没;打断处理,它回复到一半你插话进去怎么办;情绪感知,你语气里带的信息,转成纯文字之后全丢了。所以实时语音平台我们认真评估了三个,对比下来结论挺清楚的。
三方对比
| 维度 | Hume EVI 3 | OpenAI Realtime API | 豆包 Realtime |
|---|---|---|---|
| 自定义 LLM | 支持——gemini、claude、任意 | 不支持——只能用 gpt | 不支持——只能用豆包大模型 |
| 语音情感表达 | 业界最强,一等公民 | 弱——官方称"future improvement" | 好——3D 情绪空间 |
| 用户情绪识别 | 支持——从语调分析 | 有限 | 支持 |
| System prompt / context 注入 | 完全支持 | 支持 | 不支持——黑盒 |
| 工具调用 | 支持——可调你的 API | 支持 | 不支持 |
| 打断处理 | 支持——基于语调轮次检测 | 支持 | 支持 |
| 延迟 | 约 500ms 首字节 | 约 300ms | 约 700ms |
| 价格 | 按分钟计费 (Pro) | 按分钟计费 (audio) | 待定 |
表格说了大半,但有一个点得单独拎出来:OpenAI Realtime 和豆包 Realtime 是同一个致命问题,不能用你自己的 LLM。 OpenAI 锁死 gpt,豆包锁死自家大模型。做通用语音助手这无所谓,对 Mio 来说这就是死局。
原因具体是这样的:Mio 的核心差异化全在记忆、人格和情绪 context 上,这些东西活在我们服务器上,每次回复前要注入 LLM 的 context window。伴侣得知道你上周提过面试、最近一直挺焦虑、喜欢直说不喜欢绕弯子,这些 context 才是让它成为「你的伴侣」而不是「一个通用 AI」的东西。所以我们的要求很硬:对 system prompt 和 LLM 本身要有完全控制权。
豆包这边我们专门验证了三件事:支不支持自定义 system prompt,能不能动态注入 context,能不能换外部 LLM。答案分别是不支持、有限支持(只能塞 RAG 风格的知识片段,做不了行为指令)、不支持。等于一个说话很好听的黑盒,它只能是豆包,成不了你的伴侣。OpenAI Realtime 至少支持 system prompt,但锁死 gpt 意味着用不了 gemini(Mio 靠它的性价比)也用不了 claude,而且语音情感表达在官方口径里还是「future improvement」,对一个拿情感当卖点的产品来说,这不可接受。
最后选了 Hume EVI 3
整个架构一句话能讲清楚:LLM 决定说什么,Hume EVI 负责怎么说,有点像编剧和演员的分工。
LLM 当编剧决定说什么、Hume EVI 当演员决定怎么说的分工架构
LLM 根据人格、记忆、情绪状态和对话历史生成回复文本,它对这个角色是谁、这个时刻需要什么理解最深,反正它不用管语音层的事,把内容写出来就行。Hume 管表达层的全部:听对方讲话(STT 加情绪分析),判断对方什么时候说完(轮次检测),用对的情感语调把回复念出来(Octave TTS),再处理各种意外,比如被打断、被抢话、回复还没回来先垫一句。具体一轮对话是这样跑的:
-
用户说话。 Hume 同时干三件事:把语音转成文字;分析用户语调里的情绪(「听起来用户很焦虑」);判断用户说完了没——不是傻等静音超时,是从语调本身理解对话的节拍。
-
Hume 把结果送到我们服务器。 我们拿到用户文本加情绪分析,查记忆、构建 context、调 LLM(gemini 或 claude,随便换),返回回复文本。
-
Hume 把回复说出来。 Octave 自动匹配情绪合成语音,音频流式返回。
这里面最妙的设计是填充词。Hume 内置了一个叫 eLLM 的快速轻量模型,200ms 内先给一个即时反应,「嗯…」「哦!」这种,把完整回复生成的那段空隙填掉,再无缝过渡到正式回复。用户感知到的延迟几乎是零,对话里不会出现几秒钟的干等。你想想真人是怎么接话的:没有人沉默三秒然后突然讲出一段完整的话,都是先「嗯…」一下,边想边说。Hume 复刻的就是这个模式:正式回复还没生成完,先用一个即时反应把话接上。
用户:"我没拿到那个 offer。"
[~150ms] Hume eLLM: "啊..."
[~800ms] 你的 LLM 完成生成
Hume: "...真的很遗憾。我知道你多在意
这个机会。"
过渡是无缝的,用户听到的是一个连续的回应:开口很快,后面跟上的正式回复情绪也对,中间没有明显的空档。
eLLM 在 150ms 内先垫一句嗯…、正式回复 800ms 才到,从而让用户感知零延迟的时序机制
这个分工好在哪
拆开之后有几件事是一体化方案做不到的。第一,关注点分离:LLM 专心做推理、记忆检索、人格一致性这些内容层面的事,Hume 专心做听、说、表达层的情感、轮次管理,两边都不用什么都会。
第二,供应商随便换。更好的 LLM 出来了(隔几个月就来一个),换 LLM 就行,语音层不用动;Hume 把 Octave 音质升级了,LLM 侧一行不用改。每一层各自演进。
第三,情绪变成一等信号。Hume 对用户语调的分析,给了纯文字系统拿不到的信息:用户嘴上说「我没事」,语气不是这么说的。这个信号反哺给情绪引擎,让伴侣对用户状态的理解丰富很多,这个纯文字分析永远做不到。
第四,延迟的处理方式符合人的心理。人不会把沉默理解成「它在快速思考」,只会理解成断连了。一个很快的「嗯…」后面跟一段有分量的回应,感觉上既更快也更自然,比 1.5 秒沉默之后蹦出一个完美回答要好。
实时语音的成本
再说成本,这个躲不掉。实时语音 API 按分钟计费,累积速度挺吓人:一个用户每天跟伴侣聊 10 分钟,对把 Mio 当日常陪伴的人来说这真不算多,光语音一项的月成本就超过整个订阅费了。这还没算聊天、记忆、STT、主动消息。就算谈到更高量级的折扣,数字也没好到哪去。结论很直接:实时语音塞不进基础订阅,一个重度语音用户的成本就能把他付的钱花完。解决办法是分层:
| 档位 | 包含内容 |
|---|---|
| Pro | 文字聊天 + 语音消息 (TTS) + 全部功能 |
| Voice | Pro 全部 + 实时双向语音(高级定价) |
语音消息(非实时 TTS,豆包或 Octave)成本低到可以直接放进基础订阅;实时语音是完全不同的成本结构,得单独定价。这也是分阶段的原因:v0.1-0.2 先上语音消息,便宜、已验证、换了新 TTS 之后情感表现力提升很大,用户先拿到一个说话带感情的伴侣;v1.0 再把实时语音做成高级升级,给想要完整对话体验的用户。
分阶段计划
v0.1-0.2:语音消息(非实时)
- 中文 TTS:豆包 2.0——自动情绪推断,中文韵律最佳
- 英文 TTS:Hume Octave——基于 LLM 情绪理解,处理微妙语境
- STT:gpt-4o-mini-transcribe(从 v1 沿用)
- 三者都支持自动情绪推断,不需手动 SSML 标注
v1.0:实时双向语音
- 中英双语统一使用 Hume EVI 3
- 自定义 LLM(gemini/claude)作为"大脑"
- Hume 负责听、情绪分析、轮次管理、情感语音合成
- 填充词模式实现感知零延迟
- 独立 Voice 档定价
v1.x:评估与优化
- 如果 Hume 的中文质量不够,中文回退自组装流水线:gpt-4o-mini-transcribe → gemini → 豆包 TTS 2.0
- 如果够好,就用 Hume EVI 统一中英双语
为什么不等大厂的方案
第一篇里说过一个判断:大厂不会做深度情感伴侣,品牌风险摆在那。到语音这层,这个判断照样成立。OpenAI 有 Advanced Voice Mode,技术真的很强,但它永远不会让你接自己的 LLM、注入自己的记忆系统、定制情感人格,那个声音是他们的声音。Google 的 Gemini Live 也一样。这些都是为完成任务优化的通用语音接口,不是为情感连接设计的。
这样拆开之后,Mio 的声音才真正是自己的——内容从它的人格和记忆里来,语气跟着当下的对话和情绪 context 走。一个记得你的伴侣,已经超过市面上大部分产品了。再加上带感情的语音,成本和复杂度也确实都上去了,值不值得,接下来几个月的开发跑一跑就知道。
This post is also available in English.


