小程序实现语音识别转文字,坑路历程

2023-11-04

最近为小程序增加语音识别转文字的功能,坑路不断,特此记录。

微信开发者工具

开发者工具上的录音文件与移动端格式不同,暂时只可在工具上进行播放调试,无法直接播放或者在客户端上播放

debug的时候发现,工具上录音的路径是http://tmp/xxx.mp3,客户端上录音是wxfile://xxx.mp3。 忽悠呢,不是格式不同,是映射路径不同。
其实做个兼容也不难,每次提示一行文字,很丑。

采样率与编码码率限制

每种采样率有对应的编码码率范围有效值,设置不合法的采样率或编码码率会导致录音失败。详细看这个
https://developers.weixin.qq.com/miniprogram/dev/api/media/recorder/RecorderManager.start.html

一开始没有留意,导致录音不成功。
试过几次后,采用这样的配置,感觉录音识别率和体积之间比较好平衡:

1
2
3
sampleRate: 16000, //采样率
numberOfChannels: 1, //录音通道数
encodeBitRate: 96000, //编码码率

单通道基本是必选的。因为asr只支持单通道。frameSize也是可以的,但是要考虑截断对识别的影响。暂时没有用上。

录音优化

因为可能误按,于是对小于500ms的录音直接忽略。
另外,松开录音按键后,再延迟一点时间才真正stop录音。

录音文件格式

微信录音文件支持mp3和aac。这2种格式文件都比较小,aac文件体积更小。这对上传来说是件好事情,速度更快。
但是对语音识别转文字就不友好了。因为百度、阿里云ASR、讯飞的语音转文字接口都不支持aac和mp3,通常要求是pcm或者wav格式。
如果微信录音能提供wav格式,那么就不用服务器做格式转换了,但是wav格式体积是mp3、aac的5到10倍,至少短期是没戏了,这也是很多人吐槽的地方。

服务器转换录音文件格式

可以用java第三方库转换,也可以用Process调用ffmpeg转换。要注意的是,根据识别API的要求来做转换。比如阿里云asr的要求是:

支持音频编码格式:pcm(无压缩的pcm文件或wav文件)、opus,16bit采样位数的单声道(mono);
支持音频采样率:8000Hz、16000Hz;

java ProcessBuilder要使用数组传参

转换音视频,习惯用ffmpeg。安装完ffmpeg之后,用java新建进程调用。

1
Process = new ProcessBuilder("ffmpeg -i in.mp3 out.wav").start();

一直提示CreateProcess error。 后来看文档才发现,要以数组的形式传入参数。

1
Process = new ProcessBuilder("ffmpeg", "-y", "-i", "in.mp3", "out.wav").start();

这样就启动成功了。
关于java启动进程,不是本文重点,以后再写篇文章总结。

阿里云asr sdk使用问题

这个问题困扰了一天时间,回想起来真是吐血。
问题表现是微信录制的语音很多都识别不了。
最初是直接把录音mp3文件转换为pcm文件,本地能播放,但是用阿里云asr sdk却识别不了。 一开始以为是文件编码问题。特意查了asr支持的文件格式,用ffprobe检查,potplayer看属性,都没有看出问题。
甚至把启动ffmpeg进程转换也改了,用了java的库去做,还是不行。
后来为了方便测试问题,用asr的restful接口测试录音文件,都能识别! 似乎是sdk的问题。于是打开官方文档例子对比。发现用的是sdk 2.x,老铁啊你复制粘贴过来的代码竟然少了!欲哭无泪。

1
2
3
4
// TODO  重要提示:这里是用读取本地文件的形式模拟实时获取语音流并发送的,因为read很快,所以这里需要sleep
// TODO 如果是真正的实时获取语音,则无需sleep, 如果是8k采样率语音,第二个参数改为8000
int deltaSleep = getSleepDelta(len, sampleRate);
Thread.sleep(deltaSleep);

也少了对sampleRate的设置。

阿里云asr token过期

因为用的是免费版asr,没有给福报厂充值,因此token一天失效,导致联调的时候突然报错。
最后实在受不了,写了个定时任务每小时更新token。
这,就是beggar VIP?

wx.uploadFile返回值

封装了一个接口parseResponse,统一解析查询结果(文本、语音)。发现奇怪的问题:

  • 用文本查询的,可以正常解析结果
  • 用语音查询的,明明已经返回了结果,却解析不了!

只能console.log()打印出来对比

第一行是wx.request()发起文本查询。
第二行是wx.uploadFile()上传语音文件后直接语音转文字,并且查询。

wx.request返回值是json对象。
wx.uploadFile返回值是“字符串”!
wx.uploadFile返回值是“字符串”!
wx.uploadFile返回值是“字符串”!
重要的事情要说3遍。尽管Content-Type: "application/json; charset=utf8",但是微信根本不做转换!非常坑爹!

解决:对wx.uploadFile返回值进行JSON.parse(res.data),得到json对象。

更换appid和secret

因为正式小程序项目账号一直拖着没有申请,所以这段时间用的是我个人的appid和secret进行开发。
等正式账号准备好了,更新了小程序项目的appid,并且发出内部体验包。

此时已经深夜1点半,头脑有点发懵。只更新了小程序appid,竟然忘了更新服务器的appid和secret。。。
于是乎反复报错登录失败。
过了一会才反映过来,更新服务器的appi的secret,但是还是用户。才想起忘了还有storage缓存没有清除?,里面放着自定义的session。这下真机体验没问题了。
但是微信开发者工具又是登录失败。反复摸索后发现:更换小程序appid后,清除所有数据,关闭开发者工具,重新打开,这就正常了。应该是微信开发者工具的bug。

结论:深夜不宜加班写bug?。

 

https://ycwu314.github.io/p/miniapp-speech-to-text-experience/

转载于:https://www.cnblogs.com/ycwu314/p/11286849.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小程序实现语音识别转文字,坑路历程 的相关文章

随机推荐

  • 关于谷歌Chrome浏览器的翻译功能失效的一个解决方案

    前言 自从谷歌关闭了中国大陆的谷歌翻译服务 超级好用的谷歌内置的网页翻译失效了 网上给出了好多解决方案 改服务器地址 改host 刷新dns 后者去下载某些插件 但我使用下来 十分不便 这些方法经常失效 解决方法 有一天浏览完steam商店
  • Linux 学习路线图 #CSDN博文精选# #IT技术# #学习路线# #系统化学习#

    大家好 我是小C 又见面啦 文章过滤器 精选大咖干货 助力学习之路 5天20篇CSDN精选博文带你掌握系统化学习方法 专栏将挑选有关 系统化学习方法 的20篇优质文章 帮助大家掌握更加科学的学习方法 在这里 你将收获 快速掌握系统化学习的理
  • 【LPOJ】C 北京你好 dp

    做了下上学期期中考试题 乍一看以为是贪心 wa了贼多发后发现是dp 注意 一个乘客下车后如果该站点没有人上车 则结束 说明最多的人数都要首尾相连 感谢小王同学指点迷津 include
  • 【Java】学生管理系统MVC

    目录 前言 通过这一个学期的学习 我对Java的理解又多了不少 也学了很多新的知识点 这个项目写的学生管理系统 技术要求是 Springboot JPA thymeleaf MySQL 扩展加了 BootStrap 一 功能要求 二 首先我
  • JS 正则提取字符串中特定的某一部分

    有的时候 我们在项目中会遇到这种需求 提取字符串中特定的某一部分 譬如我们向后端请求数据 得到图片的URL数据 像这样 resources images beauty jpg 我们需要提取beauty jpg这一部分 该怎么做呢 今天和大家
  • 从文件 I/O 看 Linux 的虚拟文件系统

    1 引言 Linux 中允许众多不同的文件系统共存 如 ext2 ext3 vfat 等 通过使用同一套文件 I O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式 更进一步 对文件的 操作可以跨文件系
  • springboot 读取application.properties配置中信息的三种方法

    springboot 读取application properties配置中信息的三种方法 注 想了解指定义properties配置 点击 application properties配置信息 第一种 使用 value 可以注入具体的配置信
  • mybatis 获取自增id

    开发十年 就只剩下这套Java开发体系了 gt gt gt 在开发中碰到用户注册的功能需要用到用户ID 但是用户ID是数据库自增生成的 使用下面的注解mybatis的insert语句可以解决 InsertProvider type User
  • Rust 错误处理

    Rust 错误处理 概述 panic Result Result 传播错误 概述 大多数语言并不区分可恢复错误和不可恢复错误 并采用类似异常这样方式统一处理他们 Rust 没有异常 相反 它有 Result
  • 计算正多边形的面积 Gym - 101840G

    http codeforces com gym 101840 attachments 题目大意 输入n r k n代表往外扩张几次 r代表圆的内接圆半径 k代表多边形的边长 问你每次扩张多边形和内接圆的面积之和 公式 多边形的面积公式 0
  • 码分多路复用

    引子 CDMA是个很重要的通信概念 很多的大学教科书上都会提到它 甚至我们今天可能都在使用它 然而提到cdma 很少有资料提到它的思想是多么的有创意 教科书上关于cdma的章节都过于复杂 过于数学化 虽然也有一些简便的描述方式 但是却几乎没
  • kali安装DVWA

    1 我这里使用的是kali 2020 03 版的系统 默认安装了mysql 的分支版本 MariaDB apache2 php 注 MariaDB是mysql的一个分支 实接操作与mysql没有区别 kali kali whereis my
  • stm32-07-串口通信

    串口引脚对应GPIO
  • 如何使用gdb快速attach到所需进程上

    如何使用gdb快速attach到所需进程上 大家都知道 gdb的调试功能非常强大 可以attach到打开调试开关编译出来的进程上调试进程 但是在这个流程中 你首先需要ps ef grep到你那个进程 然后找到进程号 然后再使用gdb att
  • JDK多版本管理工具jenv

    JENV mac jdk版本管理工具 Mac 安装jenv可以使用brew brew install jenv 配置jenv zsh配置方式 echo export PATH HOME jenv bin PATH gt gt zshrc e
  • Grafana 任意文件读取漏洞复现

    一 漏洞描述 Grafana存在任意文件读取漏洞 通过默认存在的插件 可构造特殊的请求包读取服务器任意文件 二 漏洞影响 Grafana 8 x 三 漏洞复现 可以从登陆页面看到版本信息为 v8 2 4 此版本在漏洞射程范围之内 查看当前所
  • vue3 el-upload文件上传隐藏文件列表

    vue3 el upload文件上传隐藏文件列表 一般情况根据官方教程直接使用el upload上传是会显示一个列表在下面如图 但有时候需求是在导入后不显示这个列表比如 这里只有一个导入按钮 点击之后上传文件 不用显示文件列表 那废话不多说
  • C语言中的printf,sprintf和vsprintf的区别

    参考于 28条消息 printf sprintf vsprintf 区别 ZinanJau的博客 CSDN博客 test printf cpp 此文件包含 main 函数 程序执行将在此处开始并结束 include pch h includ
  • 常用的图像增强方法

    大规模数据集是成功应用深度神经网络的前提 例如 我们可以对图像进行不同方式的裁剪 使感兴趣的物体出现在不同位置 从而减轻模型对物体出现位置的依赖性 我们也可以调整亮度 色彩等因素来降低模型对色彩的敏感度 可以说 在当年AlexNet的成功中
  • 小程序实现语音识别转文字,坑路历程

    最近为小程序增加语音识别转文字的功能 坑路不断 特此记录 微信开发者工具 开发者工具上的录音文件与移动端格式不同 暂时只可在工具上进行播放调试 无法直接播放或者在客户端上播放 debug的时候发现 工具上录音的路径是http tmp xxx