iOS原生语音识别使用的正确姿势
2016-12-09 本文已影响7446人
b9bd2a64f47e
语音识别技术这几年在移动App上的应用越来越广,各种第三方语音识别SDK也是层出不穷,例如科大讯飞、百度语音等,同时引入语音识别技术也是一个提高App逼格的好方法😁。所以今年的WWDC上,苹果开放了他的语音识别的API 视频在这。有了语音识别技术我们开发者就可以开发出像Siri这样炫酷的应用。我们最近也要上这个功能,所以调研一些这方面的东西。本文主要介绍iOS语音识别SDK的用法。
-
首先需要在plist文件中申请语音识别和麦克风使用权限:
- 引入头文件
#import <Speech/Speech.h>
#import <AVFoundation/AVFoundation.h>
- 申请权限
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
__weak typeof(self) weakSelf = self;
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
switch (status) {
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
weakSelf.recordButton.enabled = NO;
[weakSelf.recordButton setTitle:@"语音识别未授权" forState:UIControlStateDisabled];
break;
case SFSpeechRecognizerAuthorizationStatusDenied:
weakSelf.recordButton.enabled = NO;
[weakSelf.recordButton setTitle:@"用户未授权使用语音识别" forState:UIControlStateDisabled];
break;
case SFSpeechRecognizerAuthorizationStatusRestricted:
weakSelf.recordButton.enabled = NO;
[weakSelf.recordButton setTitle:@"语音识别在这台设备上受到限制" forState:UIControlStateDisabled];
break;
case SFSpeechRecognizerAuthorizationStatusAuthorized:
weakSelf.recordButton.enabled = YES;
[weakSelf.recordButton setTitle:@"开始录音" forState:UIControlStateNormal];
break;
default:
break;
}
});
}];
}
- 核心代码
- 识别实时音频流,如下
- (void)startRecording{
if (_recognitionTask) {
[_recognitionTask cancel];
_recognitionTask = nil;
}
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error;
[audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
NSParameterAssert(!error);
[audioSession setMode:AVAudioSessionModeMeasurement error:&error];
NSParameterAssert(!error);
[audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
NSParameterAssert(!error);
_recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
AVAudioInputNode *inputNode = self.audioEngine.inputNode;
NSAssert(inputNode, @"录入设备没有准备好");
NSAssert(_recognitionRequest, @"请求初始化失败");
_recognitionRequest.shouldReportPartialResults = YES;
__weak typeof(self) weakSelf = self;
_recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
BOOL isFinal = NO;
if (result) {
strongSelf.resultStringLable.text = result.bestTranscription.formattedString;
isFinal = result.isFinal;
}
if (error || isFinal) {
[self.audioEngine stop];
[inputNode removeTapOnBus:0];
strongSelf.recognitionTask = nil;
strongSelf.recognitionRequest = nil;
strongSelf.recordButton.enabled = YES;
[strongSelf.recordButton setTitle:@"开始录音" forState:UIControlStateNormal];
}
}];
AVAudioFormat *recordingFormat = [inputNode outputFormatForBus:0];
//在添加tap之前先移除上一个 不然有可能报"Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio',"之类的错误
[inputNode removeTapOnBus:0];
[inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.recognitionRequest) {
[strongSelf.recognitionRequest appendAudioPCMBuffer:buffer];
}
}];
[self.audioEngine prepare];
[self.audioEngine startAndReturnError:&error];
NSParameterAssert(!error);
self.resultStringLable.text = @"正在录音。。。";
}
- (SFSpeechRecognizer *)speechRecognizer{
if (!_speechRecognizer) {
//要为语音识别对象设置语言,这里设置的是中文
NSLocale *local =[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
_speechRecognizer =[[SFSpeechRecognizer alloc] initWithLocale:local];
_speechRecognizer.delegate = self;
}
return _speechRecognizer;
}
- 识别本地音频文件,如下
- (IBAction)recognizeLocalAudioFile:(UIButton *)sender {
//此处设置支持的语言
NSLocale *local =[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
SFSpeechRecognizer *localRecognizer =[[SFSpeechRecognizer alloc] initWithLocale:local];
NSURL *url =[[NSBundle mainBundle] URLForResource:@"录音.m4a" withExtension:nil];
if (!url) return;
SFSpeechURLRecognitionRequest *res =[[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
__weak typeof(self) weakSelf = self;
[localRecognizer recognitionTaskWithRequest:res resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"语音识别解析失败,%@",error);
}
else
{
weakSelf.resultStringLable.text = result.bestTranscription.formattedString;
}
}];
}
- 注意
- iOS语音识别Api只支持iOS10SDK以及以后的版本,开发工具至少要Xcode8.0。
- 本文的Demo在这里下载,要看效果的话要在真机上运行。
- 谢谢阅读此文,希望它能对你有用。
2018-03-30 更新:修复iOS11状态栏菊花一直有的bug。。。。