前言
語音識別現(xiàn)在已經(jīng)在開發(fā)中越來越常見了余蟹,科大訊飛卷胯、百度等第三方庫層出不窮,在這里簡單的介紹一下iOS原生的語音識別該怎么做威酒。其原理就是錄音窑睁,然后把錄音數(shù)據(jù)傳給iOS內(nèi)部的語音識別庫,然后再導(dǎo)出來(原生語音識別所支持的版本為10.0及以上)葵孤。
實(shí)現(xiàn)
添加配置文件
在info.plist的文件中添加語音識別和麥克風(fēng)使用的配置Privacy - Speech Recognition Usage Description和Privacy - Microphone Usage Description担钮,如下圖:
導(dǎo)入類庫
#import <Speech/Speech.h>
#import <AVFoundation/AVFoundation.h>
定義相應(yīng)的控件
@property (strong, nonatomic) SFSpeechRecognizer *speechRecognizer;
@property (strong, nonatomic) SFSpeechRecognitionTask *recognitionTask;
@property (strong, nonatomic) SFSpeechAudioBufferRecognitionRequest *recognitionRequest;
@property (strong, nonatomic) AVAudioEngine *audioEngine;
@property (strong, nonatomic) AVAudioSession *audioSession;
上面的三個是iOS的語音識別的類,下面兩個是音頻的類箫津,對AVAudioEngine有興趣的小伙伴可以去看一下說明1和說明2宰啦,對AVAudioSession有興趣的小伙伴可以去看一下這里。
然后懶加載初始化相應(yīng)的類田炭,如下:
- (SFSpeechRecognizer *)speechRecognizer {
if (!_speechRecognizer) {
NSLocale *local = [[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"];
_speechRecognizer = [[SFSpeechRecognizer alloc]initWithLocale:local];
_speechRecognizer.delegate = self;
}
return _speechRecognizer;
}
- (AVAudioEngine *)audioEngine {
if (!_audioEngine) {
_audioEngine = [[AVAudioEngine alloc]init];
}
return _audioEngine;
}
- (AVAudioSession *)audioSession {
if (!_audioSession) {
_audioSession = [AVAudioSession sharedInstance];
NSError *error;
[_audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
[_audioSession setMode:AVAudioSessionModeMeasurement error:&error];
[_audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
}
return _audioSession;
}
小編在初始化語音識別類的時候使用的是zh_CN,這個的意思是語音識別的類型是中文,可以根據(jù)需要替換成其他類型欺缘。可以通過下列代碼獲得所支持的類型:
for (NSLocale *temp in SFSpeechRecognizer.supportedLocales) {
NSLog(@"國家代碼:%@,語言代碼:%@,輸入方式:%@_%@", temp.countryCode, temp.languageCode, temp.languageCode, temp.countryCode);
}
可以使用的類型為輸入方式后面的輸出丧鸯。
獲取相應(yīng)的授權(quán)
- (void)viewDidLoad {
[super viewDidLoad];
[self accessPermissions];
}
- (void)accessPermissions {
// 語音識別授權(quán)
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
BOOL isEnabled = NO;
NSString *str;
switch (status) {
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
isEnabled = NO;
str = @"不支持錄音";
NSLog(@"結(jié)果未知 用戶尚未進(jìn)行選擇");
break;
case SFSpeechRecognizerAuthorizationStatusDenied:
isEnabled = NO;
str = @"不支持錄音";
NSLog(@"用戶未授權(quán)使用語音識別");
break;
case SFSpeechRecognizerAuthorizationStatusRestricted:
isEnabled = NO;
str = @"不支持錄音";
NSLog(@"設(shè)備不支持語音識別功能");
break;
case SFSpeechRecognizerAuthorizationStatusAuthorized:
isEnabled = YES;
str = @"開始錄音";
NSLog(@"用戶授權(quán)語音識別");
break;
default:
break;
}
dispatch_async(dispatch_get_main_queue(), ^{
self.recordButton.enabled = isEnabled;
if (isEnabled) {
[self.recordButton setTitle:str forState:UIControlStateNormal];
}else {
[self.recordButton setTitle:str forState:UIControlStateDisabled];
}
});
}];
// 麥克風(fēng)使用授權(quán)
if ([self.audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
[self.audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
self.recordButton.enabled = granted;
if (granted) {
NSLog(@"麥克風(fēng)授權(quán)");
[self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
}else {
NSLog(@"麥克風(fēng)未授權(quán)");
[self.recordButton setTitle:@"麥克風(fēng)未授權(quán)" forState:UIControlStateDisabled];
}
});
}];
}
}
語音識別
開始錄音
- (void)startRecording {
if (_recognitionTask) {
[_recognitionTask cancel];
_recognitionTask = nil;
}
_recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc]init];
AVAudioInputNode *inputNode = self.audioEngine.inputNode;
_recognitionRequest.shouldReportPartialResults = YES;
_recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
BOOL isFinal = NO;
if (result) {
self.displayLabel.text = result.bestTranscription.formattedString;
isFinal = result.isFinal;
}
if (error || isFinal) {
[self.audioEngine stop];
[inputNode removeTapOnBus:0];
self.recognitionTask = nil;
self.recognitionRequest = nil;
self.recordButton.enabled = YES;
[self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
}
}];
AVAudioFormat *recordingFormat = [inputNode outputFormatForBus:0];
[inputNode removeTapOnBus:0];
[inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
if (self.recognitionRequest) {
[self.recognitionRequest appendAudioPCMBuffer:buffer];
}
}];
NSError *error;
[self.audioEngine prepare];
[self.audioEngine startAndReturnError:&error];
self.displayLabel.text = @"正在錄音蜂怎。。氢伟。";
}
結(jié)束錄音
- (void)endRecording {
[self.audioEngine stop];
if (_recognitionRequest) {
[_recognitionRequest endAudio];
}
if (_recognitionTask) {
[_recognitionTask cancel];
_recognitionTask = nil;
}
self.recordButton.enabled = NO;
self.displayLabel.text = @"";
}
綁定的語音識別代理
#pragma mark - SFSpeechRecognizerDelegate
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available {
if (available) {
NSLog(@"開始錄音");
[self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
}else {
NSLog(@"語音識別不可用");
[self.recordButton setTitle:@"語音識別不可用" forState:UIControlStateDisabled];
}
self.recordButton.enabled = available;
}
希望這篇文章對各位小伙伴有所幫助朵锣,想要Demo的小伙伴點(diǎn)擊這里(注意:語音識別只能進(jìn)行真機(jī)調(diào)試)