最近我们团队的AI问答模块刚完成上线,本月领导想做一个类豆包通话的实时语音交互功能。在调研参考豆包技术方案的过程中,我们发现了当前基于微信小程序实现的语音问答功能存在的核心问题:过度依赖外部组件导致的流畅度不足。今天就从技术实现对比的角度,和大家聊聊这次调研的背景、现存痛点。
先给不了解的朋友铺垫下核心场景:我们要做的是「语音提问-实时语音回复」的交互,类似豆包的通话模式,用户不用手动输入文字,直接语音对话就能获取AI解答。但受限于微信小程序的技术环境,我们的初始实现和豆包的流畅体验差了不少。
一、先搞懂:豆包通话的流畅体验靠什么支撑?
研究后发现,豆包的实时语音交互之所以自然,核心是「端侧预处理+云端全链路协同」的闭环设计,整个链路没有明显的等待断点:
1. 客户端:实时处理,保障输入质量与交互灵活性
豆包在客户端层面做了大量前置处理:调用麦克风采集音频后,通过RTC技术完成3A处理(回声消除AEC、自动增益AGC、噪声抑制ANS),能有效过滤环境噪声、避免回声干扰;再配合VAD语音活动检测,精准判断用户语音的起止,实现「随时打断AI回复」的核心交互——这也是流畅感的关键之一,毕竟没人愿意等AI说完一大段才能补充提问。
2. 云端:全链路自研,缩短响应延迟
云端采用「ASR→LLM→TTS」的全链路协同方案:
- ASR语音识别:直接将预处理后的音频流转为文本,支持多语种、低音量场景,识别准确率有保障;
- LLM语义理解:豆包自研大模型直接接收文本,结合对话上下文和联网信息生成回复,不用依赖第三方接口;
- TTS语音合成:生成回复文本后,实时转为自然语音(支持情绪适配、语速调整甚至声音克隆),直接以流的形式回传客户端播放。
整个过程是「音频流→文本流→音频流」的实时转换,没有明显的等待阶段,这也是其流畅度的核心支撑。
以上就是我们团队在微信小程序中实现AI语音问答功能的全链路实践,以及当前面临的核心流畅度痛点。目前我们正计划迭代类豆包通话的实时语音交互功能,对于现有方案的优化还在探索中。
如果有同学在微信小程序中做过类似的语音交互、Socket通信或音频播放相关功能,尤其是在优化流畅度、解决第三方依赖瓶颈等方面有实战经验,欢迎在评论区留言交流,一起避坑、探讨更优的实现方案~
对比豆包的方案,我们当前的实现因为受限于微信小程序的技术特性和资源限制,走了一条「依赖外部组件」的妥协之路,虽然实现了基础功能,但流畅度差距明显。
1. 核心实现链路
我们的链路是「前端→微信API→后端→第三方AI→后端→前端」的多段式衔接,且为实现AI输出文字的类打字机效果,我们引入了Socket连接来处理消息流式拼接,具体实现链路如下:
- 前端(微信小程序):调用微信原生语音识别API,将用户语音转为文字(这里完全依赖微信的API能力,无法做自定义的3A预处理和VAD检测);
- 后端:接收前端传输的文字,调用第三方AI模型(非自研)生成回复文本;
- Socket通信处理:为实现打字机效果,前端通过uni-app的Socket相关API与后端建立连接,持续接收第三方AI模型返回的文本片段并拼接,约定“DONE”等标识作为文本输出结束标志;
- 后端:待第三方AI模型完整输出文本(即前端接收到结束标志)后,再调用音频合成接口,将文本转为二进制音频文件;
- 前端:通过Socket接收二进制音频文件,调用微信WebAudioContext相关API解码并播放音频。
2. 技术实现细节:Socket与打字机效果的落地
为了提升用户感知层面的体验,我们针对AI输出文字环节做了类打字机效果优化,核心依赖Socket连接实现消息的流式接收与拼接,具体核心代码逻辑如下:
- Socket连接核心API使用(基于uni-app适配微信小程序):
// 建立Socket连接
uni.onSocketOpen连接socket
// 处理接收的消息内容,拼接文本实现打字机效果
uni.onSocketMessage处理消息内容,根据接收的内容拼接,约定结束标志DONE或者其他
// 关闭Socket连接
uni.onSocketClose关闭连接
- 文本接收完成后的音频解码与播放逻辑:
// 文本接收完成(识别结束标志)后
if(this.messageIsDoneEnd){
// 判断是否是流文件(二进制音频数据)
if(res?.data && (res?.data instanceof ArrayBuffer || (typeof ArrayBuffer === 'function' && ArrayBuffer.isView && ArrayBuffer.isView(res?.data)))){
// 调用微信WebAudioContext API解码并播放
const audioCtx = wx.createWebAudioContext()
audioCtx.decodeAudioData(res.data, buffer => {
let source = audioCtx.createBufferSource()
source.buffer = buffer
source.connect(audioCtx.destination)
source.start()
}, err => {
console.error('decodeAudioData fail', err)
})
}
return;
}
3. 最直观的痛点:流畅度不足的核心原因
即便引入了Socket实现打字机效果优化了用户感知,但这套方案的核心流畅度问题仍未解决,本质还是「链路太长、依赖太多、端侧能力缺失」:
- 依赖链冗长且可控性差:语音识别靠微信API、语义生成靠第三方AI,中间任一环节的延迟都会叠加;且Socket连接虽优化了文本展示,但无法解决第三方AI文本生成本身的延迟问题,整体链路可控性弱;
- 音频播放仍存在等待间隙:虽通过Socket实现了文本的流式展示,但音频仍需等待第三方AI完整输出文本后,才能由后端合成并通过Socket传输二进制文件,用户看到打字机效果结束后,还需等待音频加载解码,存在二次等待;
- 缺失端侧预处理能力:没有3A降噪和VAD检测,嘈杂环境下语音识别准确率低,且无法实现「实时打断」——即便用户中途想补充提问,也需等待当前音频播放完成,体验割裂;
- 额外的兼容性风险:引入Socket后,需处理连接稳定性、断连重连等问题;且微信WebAudioContext API在部分低版本微信客户端存在兼容性差异,增加了开发与维护成本。
二、总结
以上就是我们团队在微信小程序中实现AI语音问答功能的全链路实践,以及当前面临的核心流畅度痛点。目前我们正计划迭代类豆包通话的实时语音交互功能,对于现有方案的优化还在探索中。
如果有同学在微信小程序中做过类似的语音交互、Socket通信或音频播放相关功能,尤其是在优化流畅度、解决第三方依赖瓶颈等方面有实战经验,欢迎在评论区留言交流,一起避坑、探讨更优的实现方案~