iOS10苹果开放了语音识别接口,这让我们可以自己自由的把音频转为文本了。iOS的语音识别主要分为识别音频文件和识别音频缓存(按我的理解就是识别音频输入流达到实时转换的效果)。
因为iOS10对权限的要求更严格了所以在一切的工作之前我们要在info.plist文件里面增加两个节点。第一个节点:
key: Privacy - Speech Recognition Usage Description value:语音识别(这个值可以自定义,需要你描述Speech Recognition的用法)
第二个节点:
key: Privacy - Microphone Usage Description value:麦克风(这个值也是自定义的,同样是用来描述Microphone的用法的)
下面我们看看怎么识别音频文件:
首先我们要请求权限,
+ (void)requestAuthorization:(void(^)(SFSpeechRecognizerAuthorizationStatus status))handler
这个方法是SFSpeechRecognizer的类方法,SFSpeechRecognizerAuthorizationStatus是个枚举类型表示请求权限的结果,只有当status的值是SFSpeechRecognizerAuthorizationStatusAuthorized时才表示有使用语音识别的权限,增枚举类型的其他三个成员值分别是:
用户未决定SFSpeechRecognizerAuthorizationStatusNotDetermined、
拒绝SFSpeechRecognizerAuthorizationStatusDenied、
不支持SFSpeechRecognizerAuthorizationStatusRestricted
看代码:
//请求权限
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
NSURL *url = [[NSBundle mainBundle] URLForResource:@"speech" withExtension:@"m4a"];
[self recognizeAudioFile:url];
}
}];
然后我们再看具体的怎么进行语音识别:
SFSpeechRecognizer这个类是具体用来进行语音识别的,默认初始化方法init表示识别本地语言环境,就是说如果你手机是中文那么你说中文就可以直接识别了。当然了如果我们想指定识别某种语言就要使用:- (nullable instancetype)initWithLocale:(NSLocale *)locale
这个方法进行初始化了。
然后我们再创建一个SFSpeechURLRecognitionRequest类的实例,这个实例包含了音频信息。最后再调用SFSpeechRecognizer实例的
- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request
resultHandler:(void (^)(SFSpeechRecognitionResult * __nullable result, NSError * __nullable error))resultHandler;
方法,将音频信息传给苹果的服务器然后,苹果会直接返回转换后的信息。直接看代码:
SFSpeechRecognizer *recongize = [[SFSpeechRecognizer alloc] init];
SFSpeechURLRecognitionRequest *request = [[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
[recongize recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
if (result) {
self.speechText.text = result.bestTranscription.formattedString;
}
if (error) {
self.speechText.text = error.description;
}
}];
到此为止已经完成了音频文件的识别了。下面我们再说说怎样实时识别音频输入流:
识别音频输入流的步骤与上面的大体相似,最主要的不同是音频资源的区别一个是直接从文件获取另外一个是从AVAudioNode的输出数据获取的。所以我们首先要开启麦克风获取AVAudioNode输出的音频信息,这部分就不细说了直接看代码:
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryRecord error:&error];
if (error) {
self.speechText.text = error.description;
return;
}
[session setMode:AVAudioSessionModeMeasurement error:&error];
if (error) {
self.speechText.text = error.description;
return;
}
[session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
if (error) {
self.speechText.text = error.description;
return;
}
if (!auengine.inputNode) {
self.speechText.text = @"无输入节点";
return;
}
[auengine.inputNode installTapOnBus:0 bufferSize:1024 format:[auengine.inputNode outputFormatForBus:0] block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
if (buffer) {
[requestbuffer appendAudioPCMBuffer:buffer];
}
}];
[auengine prepare];
[auengine startAndReturnError:&error];
这样我们在- (void)installTapOnBus:(AVAudioNodeBus)bus bufferSize:(AVAudioFrameCount)bufferSize format:(AVAudioFormat * __nullable)format block:(AVAudioNodeTapBlock)tapBlock
这个方法的block里面就可以获取到输出的音频信息,接下来我们再识别这个信息:
第一步都是创建一个SFSpeechRecognizer实例,第二步有区别我们要创建SFSpeechAudioBufferRecognitionRequest这个对象的实例,第三步还一样的调用:- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request
的方法。
resultHandler:(void (^)(SFSpeechRecognitionResult * __nullable result, NSError * __nullable error))resultHandler;
看代码:
SFSpeechRecognizer *recognize = [[SFSpeechRecognizer alloc] init];
SFSpeechAudioBufferRecognitionRequest *requestbuffer = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
[recognize recognitionTaskWithRequest:requestbuffer resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
if (result) {
self.speechText.text = result.bestTranscription.formattedString;
}
if (error) {
self.speechText.text = error.description;
}
}];
完整的源码已经上传到了github,下载源码