避开Google Voice Search利用Google Speech API实现Android语音识别之原理
来源:互联网 发布:js切割字符串 编辑:程序博客网 时间:2024/03/29 05:39
最近在做一款Android下的语音识别软件。Android下面的语音识别做起来很容易,只需要调用Google的Voice Search就可以了,具体方法如下:
http://www.cnblogs.com/TerryBlog/archive/2010/11/12/1875875.html
使用Voice Search提供的接口虽然能很方便地实现语音识别,但是却要额外安装2M多的Voice Search,很不方便。能不能不借助Voice Search实现语音识别呢?
Voice Search的语音识别是在云端识别的,那么必然就有网络接口,只是Google没有公开而已。使用强大的Google搜索了一下,还真发现了一篇介绍这个接口的文章:http://blog.csdn.net/dlangu0393/article/details/7214728。
根据文章的描述,Gogole语音识别的网络接口地址是:
http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=zh-CN&maxresults=1
这个接口在国外应该可以,但是在国内就要把www.google.com换成www.google.com.hk,于是接口地址改成这样:
http://www.google.com.hk/speech-api/v1/recognize?xjerr=1&client=chromium&lang=zh-CN&maxresults=1(其中lang参数表示的是语言类型,maxresults表示的是最多返回多少个结果)
接口找到了,那么直接上代码吧:
一、识别所需的音频信息采集
根据文章作者的描述,需要把语音信息通过POST方式传给服务端,并且只支持wav和SPEEX这两种格式的语音。而Android上,有两个可以录音的类:MediaRecorder和AudioRecorder。前者可以录制amr格式的录音,而后者比较底层,可以录制pcm格式的录音。pcm到wav的转换相当简单,只需要加一个头信息就可以了。因此采用AudioRecorder类录音。录音的关键代码如下:
mPCMSize = 0;
int readed = 0;
int bufferSize = AudioRecord.getMinBufferSize(mFrequence,
CHANNEL_CONFIG, AUDIO_ENCODING);
byte[] buffer = new byte[bufferSize];
AudioRecord recorder = new AudioRecord(
MediaRecorder.AudioSource.MIC, mFrequence, CHANNEL_CONFIG,
AUDIO_ENCODING, bufferSize);
recorder.startRecording();
while (mRecordLock) {
readed = recorder.read(buffer, 0, buffer.length);
if (mMaxVoiceSize < readed + mPCMSize) {
stop();
continue;
}
byteCopy(mPCMSize, readed, buffer, mPcmData);
mPCMSize += readed;
}
recorder.stop();
recorder.release();
recorder = null;
其中 mMaxVoiceSize是音频缓存的最大大小,mPcmData 是一个mMaxVoiceSize大小的byte数组,用来缓存音频信息。本程序mMaxVoiceSize的值为200k,设置的比较大。一般的音频数据只要30k的缓存就足够了。mPCMSize是语音数据的总大小。
二、pcm转wav
wav其实就是一种特殊的pcm,pcm转wav只需要在pcm原始数据之前加上一段44字节的描述音频数据的头即可。Wav格式文件头说明如下:
偏移地址
字节数
数据类型
内 容
00H
4
char
"RIFF"标志
04H
4
long int
文件长度
08H
4
char
"WAVE"标志
0CH
4
char
"fmt"标志
10H
4
过渡字节(不定)
14H
2
int
格式类别(0x0001H为PCM形式的声音数据)
16H
2
int
通道数,单声道为1,双声道为2
18H
2
int
采样率(每秒样本数),表示每个通道的播放速度,
1CH
4
long int
波形音频数据传送速率,其值为通道数×每秒数据位数×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。
20H
2
int
数据块的调整数(按字节算的),其值为通道数×每样本的数据位值/8。播放软件需要一次处理多个该值大小的字节数据,以便将其值用于缓冲区的调整。
22H
2
每样本的数据位数,表示每个声道中各个样本的数据位数。如果有多个声道,对每个声道而言,样本大小都一样。
24H
4
char
数据标记符"data"
28H
4
long int
语音数据的长度
代码如下:
private class WaveHeader {
public static final int HEAD_LENGTH = 44;
public final char dataType[] = { 'R', 'I', 'F', 'F' };
public int dataLength;
public char wave[] = { 'W', 'A', 'V', 'E' };
public char fmt[] = { 'f', 'm', 't', ' ' };
public int fmtHeadLength;
public short format;
public short channels;
public int frequence;
public int tranSpeed;
public short blockAlign;
public short bits;
public char data[] = { 'd', 'a', 't', 'a' };
public int pcmLength;
public WaveHeader() {
}
public byte[] getHeader() {
byte[] head = new byte[HEAD_LENGTH];
int position = 0;
position += writeChars(head, dataType, position);
position += writeInt(head, dataLength, position);
position += writeChars(head, wave, position);
position += writeChars(head, fmt, position);
position += writeInt(head, fmtHeadLength, position);
position += writeShort(head, format, position);
position += writeShort(head, channels, position);
position += writeInt(head, frequence, position);
position += writeInt(head, tranSpeed, position);
position += writeShort(head, blockAlign, position);
position += writeShort(head, bits, position);
position += writeChars(head, data, position);
position += writeInt(head, pcmLength, position);
return head;
}
private int writeChars(byte[] head, char[] chars, int start) {
for (int i = 0; i < 4; i++) {
head[i + start] = (byte) chars[i];
}
return 4;
}
private int writeInt(byte[] head, int value, int start) {
int i = start;
start += 4;
while (i < start) {
head[i] = (byte) value;
value >>= 8;
i++;
}
return 4;
}
private int writeShort(byte[] head, short value, int start) {
int i = start;
start += 2;
while (i < start) {
head[i] = (byte) value;
value >>= 8;
i++;
}
return 2;
}
}
通过getHeader()方法获得文件头之后,把这个头放在pcm数据之前就可以了。
三、wav格式语音数据上传
核心代码如下:
URL httpUrl = null;
httpUrl = new URL(getApiUrl());
HttpURLConnection urlConnection = null;
urlConnection = (HttpURLConnection) httpUrl.openConnection();
urlConnection.setConnectTimeout(HTTP_CONNECT_TIMEOUT);
urlConnection.setReadTimeout(HTTP_READ_TIMEOUT);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestMethod("POST");
urlConnection.setAllowUserInteraction(true);
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0");
urlConnection.setRequestProperty("Content-Type", "audio/L16; rate="
+ mFrequence);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(mVoiceData);
四、JSON解析
返回结果的一个典型的JSONObject为:
{"status":0,"id":"1ab4d16b0e55172689edaa8c1d2acb99-1","hypotheses":[{"utterance":"明天早上九点开会","confidence":0.2452792},{"utterance":"明天早上 9 点开会"},{"utterance":"明天早上九点开会了"},{"utterance":"明天早上九点开会呢"},{"utterance":"明天早上九点开会吗"},{"utterance":"明天早上九点开会啦"},{"utterance":"明天早上九点开会儿"},{"utterance":"明天早上九点开会啊"},{"utterance":"明天早上九点开会的"},{"utterance":"明天早上 9 点开会吗"}]}
其中hypotheses数组里面存放的就是结果,使用Android的JSONObject类和JSONArray类很容易就能解析出结果。
- 避开Google Voice Search利用Google Speech API实现Android语音识别之原理
- 避开Google Voice Search利用Google Speech API实现Android语音识别之Demo实现
- 【Google Voice】Android 轻松实现语音识别
- 使用Google语音识别引擎(Google Speech API)
- 使用Google语音识别引擎(Google Speech API)
- 【Android开发学习45】使用google语音识别引擎(Google Speech API)<一>
- MFC使用Google Speech API进行语音识别
- 利用Google Speech API实现Speech To Text
- ios 调用google api 实现语音识别
- ios 调用google api 实现语音识别
- ios 调用google api 实现语音识别
- 使用Google语音识别引擎(Google Speech API)[3月5日修改]
- 使用Google语音识别引擎(Google Speech API)[3月5日修改]
- 使用Google语音识别引擎(Google Speech API)[3月5日修改]
- 使用Google语音识别引擎(Google Speech API)[3月5日修改]
- 【miscellaneous】使用Google语音识别引擎(Google Speech API)[3月5日修改]
- Google Voice 语音搜索
- Android 利用 Voice Search语音接口 进行语音识别结果太不准
- malloc/free和new/delete
- leetcode之 Palindrome Partitioning I&II
- PHP缓存技术
- makefile编写
- MySQL基础知识---------ALTER TABLE/CREATE DATABASE语法
- 避开Google Voice Search利用Google Speech API实现Android语音识别之原理
- osg各个命名空间的细节描述
- qwt在linux下的安装
- insert data into Oracle Clob
- yum 命令
- 北京电信今日开售4G:加1元有惊喜
- 服务器自动化安装脚本
- UML中类之间的几种关系
- 快速搭建企业级流媒体服务器方案(直播流服务器适配android和iphone)