小程序——MP3转pcm之殇

1、 需求背景html

  1. 明确需求:
    微信小程序实现语音识别。
  2. 分析需求:

    目前咱们科大讯飞平台目前已经支持语音识别相关业务,咱们只要将小程序语音上传(对接)到科大讯飞语音处理后台,就能完成上述需求。node

  3. 问题拆解:
    上述需求 => 将小程序语音按照目前接口要求的格式上传到讯飞语音接口。

2、 分析和调研问题git

  1. 小程序支持的录音格式(MP3,AAC),采样率(8k-48k)

clipboard.pngclipboard.png
clipboard.pngclipboard.png

2.科大讯飞语音接口接收的参数github

将语音转换为对应的文本和语义
bVbowRt?w=858&h=416npm

3.明确需求:小程序

  • 因为小程序支持MP3和AAC两种录音格式,可是EPG的语音接口支持分片上传,因此咱们只能选择mp3格式
  • EPG语音接口支持 四种编码格式(pcm、speex、speex、opus),采样率 8k或16k。
  • 思路:(目前的采样率认为是能够16k=> 16k不用变)

a) Mp3 => pcm
b) Mp3 => speex
c) Mp3 => amr
d) Mp3 => opus后端

  • 通过一番调研 github 或者npm包(由于小程序没有window对象,搜索资料node.js不能用浏览器下的对象)

a) 有一个工具ffmpeg(安装) 命令行转(不知足需求)
b) 【小程序社区】社区中有两种声音
(1)官方能不能增长pcm录音格式(官方给出暂时不考虑)
(2)MP3 => pcm放在服务器端作(咱们的后端推不动)
(3)【很高兴】得知github js-mp3开源库能够将MP3的arraybuffer => pcm格式的arraybuffer
https://developers.weixin.qq....微信小程序

  • 验证js-mp3能不能将MP3转为pcm格式

a) 网上下载 MP3
b) 在node.js中写对应的demo
c) 能够将MP3转为 pcm(很高兴,也没注意该MP3的采样率是多少)
d) 微信小程序demo, 将录音的mp3,将录音的MP3文件由临时文件保存到本地文件(此时不知道保存到哪里了,手机的根目录/tencent/MicroMsg/wxafiles/tem_XXXXXX, 文件名变了,文件管理功能不强大)
e) 将录音MP3(16k)试着用 js-mp3转码(很惋惜失败了,绝望)浏览器

  • 分析js-mp3转码不成功的缘由

a) MP3有几种格式服务器

clipboard.png

b) 下载ultraEdit对MP3文件头分析
音频数据帧

每一个帧都有4 字节帧头 + 2 字节CRC校验(存在是否由帧头决定)+ 尸体数据(MAIN_DATA)
 Ø  帧头
 AAAAAAAA   AAABBCCD   EEEEFFGH    IIJJKLMM

clipboard.png
图片描述

clipboard.png

c) js-mp3支持的MP3帧数据的前几位是
(1)49 68
1001001 011 01 00 0
保留 保留
(2)49 51
1001001 010 10 00 1
Mpeg2 保留
(3)FF FA
11111111 111 11 01 0
Mpeg1 layer3
(4)FF FB
11111111 111 11 01 1
Mpeg1 layer3

总结:这个包只支持采样率为32k以上的音频转码

http://www.mp3-tech.org/progr...
d) 微信MP3(16k,8k)所属格式(几个转码不成功的)
微信 wx.mp3
Ff f3 68 04
1111 1111 1111 0011 0110 1000 0000 0100
Mpeg2 Layer3 比特率 48 采样率 8000

Wx1.mp3
【开头16进制】49 44 33 03
【二级制】0100 1001 0100 0100 0011 0011 0000 0011
Mpeg2.5 layer2 比特率 24 采样率 12000

clipboard.png

FF F3
1111 1111 111 10 01 1
Mpeg2 layer3

图片描述

下载的MP3
Ff f3 40 c0
1111 1111 111 10 01 1 0100 0000 1100 0000
MPEG 2 layer3 比特率 32 采样率 22050

【绝望】js-mp3 好像不行了,重新调研其余包

3、 解决问题

  1. 调研从零开始,理清思路。
  2. 经过调研得知wav = pcm + 44字节(头信息),因而MP3=>pcm转为MP3=>wav

Pcm播放器播不了,wav能播

  1. audiobuffer-to-wav

图片描述

a) 【曙光】Mp3文件 buffer => arraybuffer
=> audioBuffer =>
wav的ArrayBuffer => buffer(写入文件)
b) Audiobuffer 这个对象是浏览器端的对象(绝望)
c) audio-decode 这个包在node端也支持https://github.com/audiojs/au...
d) 开始测试普通的MP3文件转码ok, 小程序录音的MP3文件又报错
断点调试:这个包引入 ‘is-mp3’

clipboard.png

通过分析得知:
wx MP3开头 Ff f3
支持的开头 (1)FF FA/FB (2)49 44/33
怀疑: 这难道不是真正的MP3

手动添加

clipboard.png

校验过去了,可是仍是不支持这种采样率为(16k或者8k的),转换时候报错了

  1. 【转换思路】先用 32k以上的采样率(这样起码MP3=> pcm是成功的),而后再同一种格式降低低采样率(32k=> 16k)
  2. 在node端验证完毕(js-mp3或者audio-decode)
  3. 在小程序端实现时(audio-decode报错,暂时没解决。Js-Mp3没有报错)

获得pcm格式(32k采样率)

let Mp3 = require('js-mp3');

var mp3ArrayBuffer = ...; // prepare your mp3 decoded array buffer here

    var decoder = Mp3.newDecoder(mp3ArrayBuffer);
var pcmArrayBuffer = decoder.decode(); // now you got decoded PCM data
  1. 【新问题】pcm (采样率由32k转为16k)
  2. Pcm-util

    pcm.convert(buffer, fromFormat, toFormat)
    Convert array buffer from one format to another.
    图片描述

注意:
 采样率 32k 变为 16k
 SamplesPerFrame和采样率是对应的
 BitDepth不设置的时候,默认是16
保存pcm(pcm文件大小约为MP3文件大小的10倍)文件到本地,此时用ffmpeg将pcm转为wav
(1) 用采样率为16k转换时,时长为原MP3的两倍(严重失真)
(2) 用采样率32k转换时,时长和原mp3一致(不失真)
结论: 上述pcm 32k=> pcm16k时没有成功(toFormat有问题)。
经过排查将bitDepth设为 原来的一半 8,结果 pcm 16k文件约为原mp3大小的5倍,ffmpeg 16k 转为wav播放正常(无失真)

4、对接科大讯飞语音识别Ai

  1. 测量转码耗时

录音时长(s) 转码时间(s)
10.920 7.118
5.8 3.972
1.48 0.918
提交转码后的16k pcm,能够实现语音识别
5、分析和优化
分析

  1. 实现了从0到1到过程(不用依赖后端,本身也能玩起来)
  2. 因为如今没有利用分片上传、分片转码,分片转意的过程。耗时相对较长
  3. 如今js-mp3转码只能识别 整个MP3,而分片 不是一个MP3格式的数据,是纯数据切断(致使,这个方案不能分片解码、上传)
  4. 目前耗时 在两步 MP3(32k)=> pcm(32k)=> pcm(16k)

优化
1.变两步为一步 mp3 (16k) => pcm (16k)
2.解决audio-decode 引入错误,若是能将 ,mp3的arraybuffer 分片转为audioBuffer(不依赖整个mp3头),完成 pcm(16k) 直接转换

  1. 分片上传 10s 的时长,转码耗时只是最后一个分片的2s解码和上传时间

6、收获 完成了小程序社区没人敢去尝试的一条路 办法总比问题多 沉着冷静逐一击破 后面再优化

相关文章
相关标签/搜索