google streaming voice recognition分析
chrome用到了google的语音识别webservice,下面对该webservice使用原理,即voice recognition和chrome的语音识别实现原理进行分析。详见chrome源码。
google语音识别有两个webservice,一种叫做google_one_shot_remote_engine,一种叫做google_streaming_remote_engine,简称为oneshot和streaming。如果进行http抓包,可以发现,one_shot连接的是一个端口为80的地址,streaming连接的是一个地址的443端口。
先说oneshot,这个方式现在已经被解析的差不多了。该方式是连接http://www.google.com/speech-api/v1/recognize?lang=en-us&client=chromium地址,将录好的语音数据post到这个地址,然后读取返回结果,网上资料很多,随便贴一篇。 http://blog.csdn.net/dlangu0393/article/details/7214728 。
但是,认真研究发现,android上的voice recognition和chrome并不是用的这种方式。在voice recognition或者chrome做语音识别的时候,无论说多长的句子,马上就会有返回结果,0.5秒以内。如果用oneshot的方式,会有一个等待时间,这个等待的时间是线性的,句子越长,等待时间越长。而voice recognition是常量时间,无论一句两句三句都是0.5秒内返回,这里就要讲到streaming的语音识别方式了。
streaming的基本原理是用两个http连接连服务器,叫做upstream和downstream,分别上传和下载数据,实现的关键还是在服务器,streaming用的webservice在接受完数据后马上能返回结果。接下来说一些细节。
1.upstream连接地址
https://www.google.com/speech-api/full-duplex/v1/up?key=AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY&pair=xxx&output=pb&lang=en-us&pFilter=0&maxAlternatives=5&client=chromium&xhw=xxx&continuous&interim
参数说明
key是google api key,可以申请google的开发者key,也可以用chrome里面自带的key"AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY"
pair是客户端根据时间随机生成的一个8byte的配对码,16进制表示。每次语音识别的过程中,downstream使用和upstream相同的配对码
xhw是硬件信息,可以省略
2.downstream连接地址
https://www.google.com/speech-api/full-duplex/v1/down?key=AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY& pair=xxx&output=pb
这里的key使用AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY即可,pair使用和1中pair相同的值
3.发送数据
upstream采用POST方式连接服务器,将音频文件编码的方式设置成content-type,比如conn.setRequestProperty("Content-Type","audio/x-flac;rate = 16000").之后不断的将编码好的音频数据写入连接即可,upstream只需要写数据,不需要从连接读取数据
4.客户端怎样告诉服务器数据已经写完了?
源码中写道
// The encoder requires a non-empty final buffer. So we encode a packet
// of silence in case encoder had no data already.
即客户端在所有数据都发送完后发送一个silence packet即可通知服务器数据发送完了。什么是silence packet?packet是声音数据的一个单位,是一个byte数组,全为0即表示silence,用一个byte[100]其中每个数据都为0即可表示silence packet。
5.接受数据
downstream采用GET方式连接服务器,等upstream发送了silence packet之后即可读取到数据。返回数据的格式有点特殊,返回的不是json的格式,而需要按照byte来解析。首先,返回的最开头会有4byte0,这个表示客户端连接成功。接下来的数据以chunk为单位,每次的返回有0个或者多个chunk,每个chunk的开头有4byte用来表示chunk数据部分的长度,即|4byte len|chunk data|4byte len|chunk data|。data部分是string的byte值。
原理部分基本上就这些,稍后放demo源码。
转载请注明出处