语音是我们最古老的界面。远在文字之前,远在屏幕之前,人就靠倾听彼此来认识世界;直到今天,我们仍在最初的零点几秒里评判一个声音——回答之前的那段停顿,告诉我们对面是一个在倾听的人,还是一个在处理的东西。立刻回应的声音是活的,让人等待的声音像一台照着稿子念的机器。两者之间隔着几秒钟,而一个我们勉强容忍的工具与一个我们愿意信任的伙伴之间的差别,大半就藏在这几秒里。
在今天的多数产品里,设备发出的声音是借来的。你的文字上传到某处的服务器,声音再传回来,家里那台机器只是一根很长的线末端的喇叭。与此同时,开源模型已经悄悄越过了门槛:Qwen3-TTS-12Hz-0.6B-CustomVoice,6 亿参数,九个各具特色的音色,自然的韵律,以 Apache-2.0 开放。问题已经不再是机器能不能把话说好,而是那台早就摆在角落里的、便宜的小机器——网络存储、迷你主机、工业网关——能不能自己把话说好。
二十秒的停顿
我们选的机器刻意地普通:Intel Core Ultra 5 225H,一颗笔记本级别的芯片,4 个性能核、8 个能效核、2 个低功耗核,Arc 集成显卡,没有任何独立显卡。32 GB 内存,运行系统镜像只读的 Linux,而且在我们使用它的全过程中,它一直在为机主跑着别的任务。我们没有往系统里装任何东西,没有改驱动和固件,也没有用容器。部署的一切都放在数据盘的一个目录里。
在这台机器上,官方 PyTorch 实现和 Intel 的 OpenVINO 参考 notebook 说话的方式是一样的:先把整句话组织完,然后才开口——像一个坚持把整封回信写完再读出来的人。我们用实时率衡量速度:每生成一秒语音需要几秒计算,大于 1 就跟不上自己的声音。在三条密封测试句上,参考路径落在 2.19 到 2.85 之间,第一个字要等十五到二十秒才出现。
想想你上一次问设备一个问题然后等待的情形。等到什么时候,等待本身就成了答案?一句话等二十秒,不是产品。它只是在证明产品有可能存在。
边想边说
人不会先在心里写好一段话再张嘴。人是说几个字,趁这几个字还在空气里的时候,已经在组织下一句。我们把推理路径重建成同样的方式:模型的语言部分逐帧预测声音,每帧八十毫秒;每攒够五帧——十分之四秒的语音——就交给运行在集成显卡上的有状态声码器变成波形,而此时 CPU 已经在生成下一块了。音频一边生成,一边经过一个有界队列流向喇叭,从不等到句子结束。
数字来自目标机器上一次三十分钟的常驻运行:一个进程,357 句,九个音色轮换,每轮之间空闲十秒——像一个房间,而不是一个跑分循环。第一个声音在文字输入后 0.37 秒到来,每一次都落在 0.35 到 0.54 秒之间。实时率的中位数是 0.734,也就是说,机器生成语音的速度已经是播放速度的 1.36 倍。内存峰值 2.4 GB,之后是一条平线,整个半小时只增长了 756 KB。357 句全部完成,播放器零错误,中途零欠载,而且每一句生成的声学 token 都与同文本、同音色的基线逐位一致。
和同一台机器上的批式 INT8 参考实现相比:每秒语音的计算量减少到三分之一到四分之一,第一个字提前约四十倍到来,峰值内存减半——2.4 GB 取代 4.7 GB。引擎启动后 6.7 秒模型就绪,之后一直留在内存里;九个音色随意切换、不重新加载;按一下键就能停下正在说的一句;某一句失败了,下一句照常播放。
“三分之一秒就开口的机器,不是把同一件事做得更快。它在做另一件事。”
三分之一秒就开口的机器,不是把同一件事做得更快。它在做另一件事。二十秒是一次请求和一次交付;三分之一秒是一次回应。前者属于工作流,后者属于对话,而无论音频的质量多高,都无法把一个声音从前一类挪到后一类。在这个尺度上,延迟不是性能指标,而是"被念给你听"和"有人在和你说话"之间的差别。
我们改了什么
这些结果不是靠更快的芯片得来的,而是来自质子梯度端侧推理栈里的六项技术。每一项都有名字,都有量出来的效果;每一项我们都不会在这里展开细节。
第一项是有状态流式声码器。我们的流式解码器诞生在 Apple 芯片上;这次把同一套算法搬到 OpenVINO,跑在 Intel 集成显卡上。它以 0.4 秒为一块解码语音,并把自己的状态从上一块带到下一块,于是接缝消失了:逐块输出与整句输出的信噪比达到 115.9–116.4 dB。顺路修好了参考解码器动态形状导出的问题,31 帧的解码从 4.56 秒降到 0.47 秒。
第二项是码本预测器的拆头推理。Qwen3-TTS 每一帧要预测十六个声学码本,其中十五个由一个每秒语音要跑几百次的小循环完成。我们重组了这个循环,让每一步只碰它真正需要的权重。十五步循环从 40.1 毫秒降到 32.3 毫秒,三条测试句的实时率从 0.93、0.83、0.84 降到 0.80、0.74、0.72,输出没有变动一个比特。
第三项是 INT8 权重压缩方案:哪些组件压到八比特权重、怎么压、怎么证明没有损失。主语言组件从 887 MB 减到 444 MB,码本预测器从 220 MB 减到 110 MB,预测器的逐帧循环从约 79 毫秒提速到 45 毫秒,声码器保持 FP16。盲听中,两条中文样本与未压缩版本无法分辨。
第四项是横跨 CPU 与集成显卡的异步流水线。token 生成跑在四个性能核上,声码器跑在 Arc 显卡上,任一时刻最多一个解码在途,音频块按序离开。解码与生成重叠,而不是排在生成后面。
第五项是性能核亲和调度。一颗混合架构芯片像一支由四个短跑选手和十个散步者组成的队伍,对于一场由成千上万个小步组成的接力,直觉的做法——让所有人都上跑道——恰恰是错的。七组单变量实验把常驻实时率从 8 线程不绑核的 1.06 压到 4 线程绑定性能核的 0.86,这是拆头之前的数据。散步者一上场,所有人都慢了。
第六项是常驻服务框架:一个进程,九个音色,不重载;一个永远装不下超过一句话的音频队列;取消后继续;任何一句失败都被隔离。在一次主动取消和一次注入的播放器故障之后,下一句的输出都与正常运行逐位一致。正是这一层,把"一个跑得快的模型"变成了"一个可以一直开着的东西"。
同一套算法,不同的硅
这个项目里我们最在意的不是那台 Intel 设备,而是我们为 Apple 芯片——iPhone 和 iPad 上的 Metal——构建的流式引擎,搬到带 Intel 集成显卡的 x86 上时,算法本身没有变。声码器的状态管理、分块的节奏、有界的输出、取消的语义,全部原样过来了;变的只是执行后端。
“智能在算法里。底下的硅,只是部署细节。”
智能在算法里。底下的硅,只是部署细节。端侧 AI 技术栈就该是这个样子,也正因为如此,我们才能坦然地说:同一个语音引擎,属于手机,属于存储盒子,属于汽车,也属于机器人。这些地方的硬件各不相同,思考的方式是同一个。
留在家里的声音
当语音在被听到的地方生成,几件事会同时发生。你输入的文字和你听到的声音从不离开设备——根本不存在能让它们离开的网络路径。三分之一秒开口,是"会回应的声音"和"在念稿的声音"之间的差别。而这一切跑在人们已经拥有的硬件上:没有独立显卡,2.4 GB 内存,十四个核里用四个,一台 32 GB 的机器其余部分照常干自己的活。357 句之后内存仍然平直的常驻服务,有产品的形态,而不是演示的形态。
同样的形态适合家用机器人、自助终端、车里的助手,以及任何本该不必向数据中心请示就能开口的设备。一个 6 亿参数的模型,在一台小型 x86 设备上三分之一秒开口——这不是研究趣闻,这是语音交互不再需要云端的那个节点。
让家里的机器找到自己的声音,并把它留在家里。