当前位置: 首页 > 后端技术 > Node.js

小程序—MP3转PCM

时间:2023-04-03 23:59:20 Node.js

一、需求背景明确需求:微信小程序实现语音识别。需求分析:目前我们科大讯飞平台已经支持语音识别相关业务。我们只需要将小程序的语音上传(对接)到科大讯飞语音处理后台即可完成上述需求。问题解决:以上需求=>将小程序的语音按照当前界面要求的格式上传到讯飞语音界面。2、分析排查问题小程序支持的录音格式(MP3、AAC)和采样率(8k-48k)小程序支持MP3和AAC两种录音格式,但是EPG的语音接口支持分片上传,所以我们只能选择mp3格式。EPG的语音接口支持四种编码格式(pcm、speex、speex、opus),采样率为8k或16k。思路:(当前采样率认为是16k=>16k不变)a)Mp3=>pcmb)Mp3=>speexc)Mp3=>amrd)Mp3=>opusaftersomeresearchgithubornpmpackage(因为小程序没有window对象,搜索数据node.js无法使用浏览器下的对象)a)有个工具ffmpeg(安装)命令行转换(不满足要求)b)【小程序社区】社区有两种声音(1)官方能不能增加pcm录音格式(官方暂时不考虑)(2)MP3=>pcm在服务端做(我们后台推不出来)(3)[太开心]学到了githubjs-mp3开源库可以转换MP3arraybuffer=>pcmformatarraybufferhttps://developers.weixin.qq....验证js-mp3可以将MP3转换成pcm格式a)在线下载MP3b)在node.js中写相应的democ)将MP3转成pcm(很开心,我没注意MP3的采样率)d)微信小程序demo,将录制的MP3文件保存到一个临时文件到本地File(此时不知道保存在哪里,手机根目录/tencent/MicroMsg/wxafiles/tem_XXXXXX,文件名变了,文件管理功能不强大)e)尝试用js-mp3转码录音MP3(16k)(不幸失败,无望)分析js-mp3转码不成功的原因a)MP3有几种格式b)下载ultraEdit分析MP3的文件头文件。音频数据帧的每一帧都有一个4字节的帧头+2个字的SectionCRC校验(是否存在由帧头决定)+尸体数据(MAIN_DATA)?帧头AAAAAAAAAAABBCCDEEEEFFGHIIJJKLMMc)MP3帧的前几位js-mp3支持的数据是(1)4968100100101101000ReservedReserved(2)4951100100101010001Mpeg2Reserved(3)FFFA1111111111111010Mpeg1layer3(4)FFFB1111111111111011Mpeg1layer3总结:本包只支持采样率32k以上的音频转码http://www.mp3-tech.org/progr...d)微信MP3(16k,8k)格式(几次转码失败)WechatWX.MP3FFF3680411111111111111110011011010001000100000000100MPEG2MPEG2层3比率48取样率8000wx1.mp3[开始hexadecimal]4949443303[二级系统]443303[bitrate24samplingrate12000??ffF3111111111110011mpeg2layer3downloadMP3FFF340C01111111111101000000000000mpeg2layer3samplingrate22050[绝望]js-mp3似乎不再工作了,所以我'我会重新调查其他包裹通过研究知道wav=pcm+44字节(头信息),所以MP3=>pcm转MP3=>wavPcm播放器不能播放,wav可以播放audiobuffer-to-wava)【曙光】Mp3文件缓冲区=>arraybuffer=>audioBuffer=>wav的ArrayBuffer=>buffer(写入文件)b)Audiobuffer这个对象是浏览器端的对象(绝望)c)audio-decode这个包也支持https://github.com/audiojs在node端/au...d)开始测试正常的MP3文件转码ok,小程序录制的MP3文件报错断点debugging:thispackageintroduced'is-mp3'经过分析发现:wxMP3开头Fff3支持开头(1)FFFA/FB(2)4944/33疑惑:这不是已经手动添加验证的真实MP3吗,但是还是不支持这个采样率(16kor8k),转换时报错【转换思路】先使用32k以上的采样率(所以至少MP3=>pcm是成功的),然后在同样的格式下降低采样率(32k=>16k)并在小程序端实现时在节点端(js-mp3或audio-decode)验证(audio-decode报错,暂未解决。Js-Mp3没有报错)获取pcm格式(32k采样率)letMp3=require('js-mp3');varmp3ArrayBuffer=...;//在这里准备你的mp3解码数组缓冲区vardecoder=Mp3.newDecoder(mp3ArrayBuffer);varpcmArrayBuffer=decoder.decode();//现在你得到了解码的PCM数据[新问题]pcm(采样率从32k更改为16k)Pcm-utilpcm.convert(buffer,fromFormat,toFormat)将数组缓冲区从一种格式转换为另一种格式。注意:?采样率32k变为16k?SamplesPerFrame和采样率是对应的?不设置BitDepth时,默认为16将pcm(pcm文件大小约为MP3文件大小的10倍)文件保存到本地,此时,使用ffmpeg将pcm转wav(1)16k采样率转换时,时长是原MP3的两倍(严重失真)(2)32k采样率转换时,时长与原MP3相同原版MP3(无失真)结论:上面的pcm32k=>pcm16k没有成功(toFormat有问题)。经查,bitDepth设置为原来8的一半,结果pcm16k文件大小是原来mp3的5倍左右,ffmpeg16k转wav可以正常播放(不失真)。Duration(s)转码时间(s)10.9207.1185.83.9721.480.918转码后提交16kpcm,可实现语音识别5.分析优化分析实现从0到1的过程(不依赖后台,你也可以自己玩)因为没有上传、转码、分块转码的过程。这需要相对较长的时间。现在js-mp3转码只能识别整个MP3,分片的不是MP3格式数据,而是纯数据切分(导致本方案无法解码上传分片)。目前分两步到MP3(32k)=>pcm(32k)=>pcm(16k)优化1.变两步为一步将piece转换为audioBuffer(不依赖整个mp3header),以及pcm(16k)完成。10s的上传时间直接换成片,转码时间只有2s最后片的解码上传时间。一条没人敢尝试的路?解决办法总是比问题多ci冷静地一个一个突破ci后期优化