flow: 语音唤醒—>建立(连接后端WSS & ASR WSS)—>录音—>ASR—>后端WSS—>获取大模型响应的音频url—>边下边播
2025/06/16更新
经过长时间的测试和修复,记录一下遇到的问题。
- 唤醒功能会占用录音资源,录音功能也会占用录音资源,可能出现唤醒后,资源未及时释放,导致录音失败。所以在录音之前,先手动释放录音资源。
- 因为通过判断ASR的断句作为录音结束结果,所以当断句出现,就直接终止ASR,然后在得到后端返回消息后,重新连接ASR。”
- ASR有可能会因为各种原因卡住,所以应该做个超时的判断,防止长时间卡在聆听状态。
2025/05/28更新
将后端的asr转移至前端,采用阿里的语音识别api,减少发送录音的时间。
- 由于阿里的wss如果十秒不发送信息将会停止连接,所以需要每过指定时间就发送一个空语音消息
- 阿里的asr会返回每一句的完整结果,并且有对应type字段,通过判断type知道用户完成了一次说话
- 判断一句话结束的间隔可以自设置,把他调高一些防止用户口吃导致提前结束语句
- 阿里控制台可以训练简单模型和设置热词,设置后,需要在代码携带的参数中指定模型和热词,否则无效
前文
flow: 语音唤醒—>建立ws连接—>录音—>pcm转wav转base64—>ws发送录音—>获取大模型响应的音频url—>边下边播
后端
简单说一下后端,后端是ws连接,建立成功后,发送wav转换的base64格式string。
如果decode success,后端会返回一个url给前端播放。
如果decode error,后端会关闭连接。
安卓
语音唤醒使用讯飞的语音唤醒SDK
- 进入讯飞的控制台,创建一个应用,随意创建。
- 进入应用详情页,选择语音唤醒,(我没有用语音唤醒(新版)的sdk,没用明白。)
- 输入你要的唤醒词并提交,前往SDK下载中心下载生成的指定SDK资源
- 在SDK下载中心,找到【回到旧版】按钮,下载旧版的语音唤醒SDK
- 下载完成后,将文件夹中libs内的资源全部剪贴到我们自己的安卓项目的lib里,并在AndroidManifest.xml添加权限(具体见SDK文档)
- 在编写唤醒对象的代码中,要添加
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=你的appid");,否则无法启动唤醒对象 - 接入唤醒对象后,在唤醒成功的回调中,建立ws连接。
建立websocket连接
- 使用okhttp3的websocket功能,先定义好初始化ws的函数
- 唤醒成功后,对ws进行初始化,在建立连接成功的回调中,启动录音进程
录音功能
- 使用安卓的AudioRecord实现录音。设置一个录音标识变量,用于记录录音是否结束
- 循环通过AudioRecord对象获取当前声音的byte,将byte写入buffer数组中
- 录音开始后,每次都记录当前分贝。如果连续出现5个及以上的分贝值大于指定阈值,说明录音开始,进行记录
- 判断录音开始了,记录如果连续出现2个及以上的分贝值小于指定阈值,结束录音。
- 在结束录音后,对保存的buffer进行格式转换,先转为wav再转换为base64,通过ws发送
边下边播
- 在ws收到消息后,得到在线音频的url
- 使用临时文件下载在线音频,同时调用MediaPlayer对象取播放这个临时文件,实现边下边播功能
连续对话
- 播放在线音频后,判断ws是否关闭(设置一个状态量,在ws的关闭回调中判断是否关闭)
- 如果关闭回到唤醒状态,否则再次进入录音模式,进行第n轮对话
注意事项
- 录音时候要设置最小录音时间和最大录音时间。
- ws和文件、录音、播放器都要对异常进行监控判断,及时抛出错误,防止app卡在某个环节。