0%

使用安卓实现一个语音助手

flow: 语音唤醒—>建立(连接后端WSS & ASR WSS)—>录音—>ASR—>后端WSS—>获取大模型响应的音频url—>边下边播

2025/06/16更新

经过长时间的测试和修复,记录一下遇到的问题。

  1. 唤醒功能会占用录音资源,录音功能也会占用录音资源,可能出现唤醒后,资源未及时释放,导致录音失败。所以在录音之前,先手动释放录音资源。
  2. 因为通过判断ASR的断句作为录音结束结果,所以当断句出现,就直接终止ASR,然后在得到后端返回消息后,重新连接ASR。”
  3. ASR有可能会因为各种原因卡住,所以应该做个超时的判断,防止长时间卡在聆听状态。

2025/05/28更新

将后端的asr转移至前端,采用阿里的语音识别api,减少发送录音的时间。

  1. 由于阿里的wss如果十秒不发送信息将会停止连接,所以需要每过指定时间就发送一个空语音消息
  2. 阿里的asr会返回每一句的完整结果,并且有对应type字段,通过判断type知道用户完成了一次说话
  3. 判断一句话结束的间隔可以自设置,把他调高一些防止用户口吃导致提前结束语句
  4. 阿里控制台可以训练简单模型和设置热词,设置后,需要在代码携带的参数中指定模型和热词,否则无效

前文

flow: 语音唤醒—>建立ws连接—>录音—>pcm转wav转base64—>ws发送录音—>获取大模型响应的音频url—>边下边播

后端

简单说一下后端,后端是ws连接,建立成功后,发送wav转换的base64格式string。

如果decode success,后端会返回一个url给前端播放。

如果decode error,后端会关闭连接。

安卓

语音唤醒使用讯飞的语音唤醒SDK

  1. 进入讯飞的控制台,创建一个应用,随意创建。
  2. 进入应用详情页,选择语音唤醒,(我没有用语音唤醒(新版)的sdk,没用明白。)
  3. 输入你要的唤醒词并提交,前往SDK下载中心下载生成的指定SDK资源
  4. 在SDK下载中心,找到【回到旧版】按钮,下载旧版的语音唤醒SDK
  5. 下载完成后,将文件夹中libs内的资源全部剪贴到我们自己的安卓项目的lib里,并在AndroidManifest.xml添加权限(具体见SDK文档)
  6. 在编写唤醒对象的代码中,要添加SpeechUtility.createUtility(context, SpeechConstant.APPID +"=你的appid");,否则无法启动唤醒对象
  7. 接入唤醒对象后,在唤醒成功的回调中,建立ws连接。

建立websocket连接

  1. 使用okhttp3的websocket功能,先定义好初始化ws的函数
  2. 唤醒成功后,对ws进行初始化,在建立连接成功的回调中,启动录音进程

录音功能

  1. 使用安卓的AudioRecord实现录音。设置一个录音标识变量,用于记录录音是否结束
  2. 循环通过AudioRecord对象获取当前声音的byte,将byte写入buffer数组中
  3. 录音开始后,每次都记录当前分贝。如果连续出现5个及以上的分贝值大于指定阈值,说明录音开始,进行记录
  4. 判断录音开始了,记录如果连续出现2个及以上的分贝值小于指定阈值,结束录音。
  5. 在结束录音后,对保存的buffer进行格式转换,先转为wav再转换为base64,通过ws发送

边下边播

  1. 在ws收到消息后,得到在线音频的url
  2. 使用临时文件下载在线音频,同时调用MediaPlayer对象取播放这个临时文件,实现边下边播功能

连续对话

  1. 播放在线音频后,判断ws是否关闭(设置一个状态量,在ws的关闭回调中判断是否关闭)
  2. 如果关闭回到唤醒状态,否则再次进入录音模式,进行第n轮对话

注意事项

  1. 录音时候要设置最小录音时间和最大录音时间。
  2. ws和文件、录音、播放器都要对异常进行监控判断,及时抛出错误,防止app卡在某个环节。