最近iOS项目中需要用到语音识别技术(也被称为自动语音识别,英语:Automatic Speech Recognition, ASR)。去google搜索了一下,发现语音识别做的不错的有谷歌,微软和科大讯飞。但是微软的语音识别只能在window平台,科大讯飞的语音识别现在主要是中文和英文,而谷歌的语音识别是可以支持多国语言的,考虑到项目以后可能会有多种语言,所以我选择用谷歌的语音识别。
这里有一篇文章,比较详细的对比了三种语音识别:Google,微软,科大讯飞的语音识别引擎对比。
语音识别的流程包括两个步骤:1.语音录入; 2.语音识别.
语音录入
语音录入的方法我使用了两种:
1.参照官方文档例子SpeakHere(使用了OC,C++混编,后来发现有些OC方法,在iOS 7中已经不建议使用了)
2.使用AVAudioRecorder来录音(建议使用第二种方法)。
注意:从查得的资料来看,使用谷歌语音搜索的音频编码暂时可用的有flac,speex,wav三种。网上说flac在iOS上获得比较复杂,speex暂不清楚,wav是可以得到的。获取wav编码格式的设置方式如下:
#pragma mark - #pragma mark 录音设置 - (NSString *) audioRecordingPath { return [NSTemporaryDirectory() stringByAppendingFormat:@"voice.wav"]; } - (NSDictionary *) audioRecordingSettings{ NSDictionary *result = nil; /* Let's prepare the audio recorder options in the dictionary. Later we will use this dictionary to instantiate an audio recorder of type AVAudioRecorder */ NSMutableDictionary *settings = [[NSMutableDictionary alloc] init]; [settings setValue:[NSNumber numberWithInteger:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; [settings setValue:[NSNumber numberWithFloat:16000] forKey:AVSampleRateKey]; [settings setValue:[NSNumber numberWithInteger:1] forKey:AVNumberOfChannelsKey]; [settings setValue:[NSNumber numberWithInteger:AVAudioQualityLow] forKey:AVEncoderAudioQualityKey]; result = [NSDictionary dictionaryWithDictionary:settings]; return result; }
录音完成之后,将音频文件保存,然后进行语音识别。
语音识别
一、从音频输入设备获取原始数据。二、对原始数据进行包装、编码。三、将编码后的音频POST至接口地址。四、分析处理接口返回的JSON并得出结果。
地址:http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=zh-CN&maxresults=1xjerr错误标准
client
客户端类型
lang
待识别语言类型,en-US是英文,中文为zh-CN(其余语言代码参考:http://msdn.microsoft.com/en-us/library/ms533052(v=vs.85).aspx)
maxresults
最大返回识别结果数量,多个结果在hypotheses列表中保存
请求方式:HTTP POST头部信息:Content-Type: audio/x-flac; rate=16000 (注:Content-Type根据所使用的编码格式不同而不同,详见文章底部。rate为音频采样率。)请求数据:编码后的音频数据
FLAC或WAV或SPEEX
iOS语音识别请求实现代码:
- (void)beginRecognition { NSURL *url = [NSURL URLWithString:@"http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=en"]; ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url]; [request setRequestMethod:@"POST"]; NSString *filePath_voice = [self audioRecordingPath]; [request appendPostDataFromFile:filePath_voice]; [request addRequestHeader:@"Content-Type" value:@"audio/L16; rate=16000"]; [request setDidFailSelector:@selector(recognitionFailed:)]; [request setDidFinishSelector:@selector(recognitionFinished:)]; request.delegate=self; [request startAsynchronous]; }
返回结果:
{ "status":0,//返回状态 "id":"", "hypotheses"://结果列表 [ { "utterance":"hello", //语音所转换的文字 "confidence":0.8394497 //识别信心度 } ] }
因为项目中语音是用来做搜索用,基本输入几个词汇就行,不需要大篇幅如短信一般。所以,我希望能在我说完话后,自动停止录音。这样,我们需要自动识别什么时候录入完毕了。
自动识别语音录入完毕
基本流程:
定时器检测实现方法以及相关注释:
-(void)refresh:(id)sender { //发送updateMeters消息来刷新平均和峰值功率 [audioRecorder updateMeters]; //此计数是以对数刻度计量的,-160表示完全安静,0表示最大输入值。 //为方便,我们将其转换为0-1,0代表完全安静,1代表最大音量。 float peakPowerForChannel = pow(10, 0.05*[audioRecorder peakPowerForChannel:0]); float averagePowerForChannel = pow(10, 0.05*[audioRecorder averagePowerForChannel:0]); NSLog(@"Average input: %f Peak input: %f", peakPowerForChannel,averagePowerForChannel); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; averagePassResults = ALPHA * averagePowerForChannel + (1.0 - ALPHA) * averagePassResults; indicateHigh.alpha = averagePassResults; if (lowPassResults > 0.55f) {//此时mic接收到震动 blowDetected = YES; } else { if (blowDetected) { blowDetected = NO; [self stopRecord]; NSLog(@"录音完成"); } } }
blowDetected是一个bool值,因为一开始录音和完成录音都是电频等级较低的时候,所以需要一个开关来区分,否则录音没刚始就结束了。
indicateHigh是个view,时刻改变透明度以告诉用户有人在说话,你也可以用其他方式来指示。
lowPassResults通过低频滤波算法得到,有兴趣的可以研究一下。其中ALPHA这里值为0.05.
好了,到这里语音识别需要的东西基本就完成了。
其实这篇文章只能算是一个汇总吧,把我需要的东西都记在这里,非常感谢网络上那些乐于分享的同学。
参考:
Iphone开发之音频101:
点击打开链接
检测用户向麦克吹气:
点击打开链接
自动识别语音录入完毕:
点击打开链接
"Unknown type name 'class'; did you mean 'Class'?"(OC与C++混编发生的问题):
点击打开链接
CADebugPrintf.h file not found:
点击打开链接
Google,微软,科大讯飞的语音识别引擎对比:
点击打开链接