在百度语音SDKDemo的基础上保存语音并进行识别
项目参考
最近在做公司的一个项目,基于百度的语音识别技术,做了一个API开放平台,准备在里面添加一部分自己的功能,对应的,平台做了就需要考虑提供配套的调用功能,在这里分享一下对百度语音SDK Demo一些使用心得
整个唤醒识别的过程解析如下:
- 语音唤醒
- 录音
- 语音交互结束后自动退出
- 返回识别结果
SDK中封装了唤醒的方法和识别的方法,现在需要做的就是把步骤2-4替换为自己的方法。
录音
在demo中已经提供了android音频流和需要添加的权限,可以参考demo中对应的文件进行学习
package com.baidu.aip.asrwakeup3.core.inputstream;
public class MyMicrophoneInputStream extends InputStream
int bufferSize = AudioRecord.getMinBufferSize(16000,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) * 16;
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
这里提供了一个单例的音频流,设置了了录音文件的相关参数,为16000HZ,单声道,保存格式为16Bit,这些参数限定了从音频流里面获取数据进行保存,对音频数据进行分析等使用的参数,也是现在网上各语音分析平台要求上传的参数。
从音频流中获取数据时,使用了与创建音频流时相同的bufferSize大小,同时要求流操作需要放到子线程中进行操作,如果放在UI线程中,会阻塞UI线程
package com.baidu.aip.asrwakeup3.core.recog;
public class MyRecognizer {
inputStream.start();
int bufferSize = AudioRecord.getMinBufferSize(16000,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) * 16;
int byteCount = 0;
byte[] bytes = new byte[bufferSize];
int count = 0;
while (inputStream.getRecordingStatus() && (byteCount = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, byteCount);
if (calculateVolume(bytes,16) == 0 ) {
count++;
} else {
count = 0;
}
if (count > 1) {
break;
}
}
注意:在使用过程中,遇到因为mic被其他应用占用导致从流中读取不到数据的问题,而且没有错误提示,如果遇到类似的问题,请进行排查是否是类似问题
说话判断
calculateVolume方法是用来判断录音中是否存在人声音的,实现照抄网上的方法,这里注意方法输入的参数和采集到的音频流参数保持一致,这里在两个录音返回数据都判断结果为0时结束录音数据的采集,结束录音进行结果识别
//识别是否存在说话
public int calculateVolume(byte[] var0, int var1) {
int[] var3 = null;
int var4 = var0.length;
int var2;
if(var1 == 8) {
var3 = new int[var4];
for(var2 = 0; var2 < var4; ++var2) {
var3[var2] = var0[var2];
}
} else if(var1 == 16) {
var3 = new int[var4 / 2];
for(var2 = 0; var2 < var4 / 2; ++var2) {
byte var5 = var0[var2 * 2];
byte var6 = var0[var2 * 2 + 1];
int var13;
if(var5 < 0) {
var13 = var5 + 256;
} else {
var13 = var5;
}
short var7 = (short)(var13 + 0);
if(var6 < 0) {
var13 = var6 + 256;
} else {
var13 = var6;
}
var3[var2] = (short)(var7 + (var13 << 8));
}
}
int[] var8 = var3;
if(var3 != null && var3.length != 0) {
float var10 = 0.0F;
for(int var11 = 0; var11 < var8.length; ++var11) {
var10 += (float)(var8[var11] * var8[var11]