语音识别
坑一、授权的几个枚举一定要注意千万别写错了,细心点莫有问题!!
语音合成
iOS7.0 后苹果推出的
神坑、在设置AVAudioSession的分类是一定要注意其类型。
/* 使用这一类别的背景声音,如雨,汽车引擎噪音等。混合与其他音乐。 */
AVAudioSessionCategoryAmbient;
/* 使用这个类别作为背景声音。其他音乐也会停止演奏。*/
AVAudioSessionCategorySoloAmbient;
/* 用这一类别来播放音乐。*/
AVAudioSessionCategoryPlayback;
/* 在录制音频时使用这个类别.*/
AVAudioSessionCategoryRecord;
/* 在录制和回放音频时使用这一类别。 */
AVAudioSessionCategoryPlayAndRecord;
/* 当使用硬件编解码器或信号处理器时,请使用这一类别不播放或录制音频。 */
AVAudioSessionCategoryAudioProcessing
//设置方法,因为我们还需要识别播放,所以选择这个AVAudioSessionCategoryPlayAndRecord类型,使用别的播放会报错 Failure starting audio queue
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
注意:使用AVAudioSessionCategoryPlayAndRecord类型默认是听筒播放,设置为扬声器有两种方法:
方法一:可以用该方法来实现听筒和扬声器切换播放
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
方法二
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
1、获取权限,将下面的代码放到Info.plist中
<key>NSMicrophoneUsageDescription</key> <string>App需要您的同意,才能访问麦克风</string> <key>NSSpeechRecognitionUsageDescription</key> <string>App需要您的同意,才能使用语音识别技术</string>
2、几个注意
//请求授权使用的枚举
//SFSpeechRecognizerAuthorizationStatusNotDetermined : 语音识别未授权
//SFSpeechRecognizerAuthorizationStatusDenied :用户未授权使用语音识别
//SFSpeechRecognizerAuthorizationStatusRestricted :语音识别在这台设备上受到限制
//SFSpeechRecognizerAuthorizationStatusAuthorized :已授权
详解AVAudioSession参考:(http://www.jianshu.com/p/331a4455ba7f)
3、全部代码
//
// SpeechRecognitionViewController.m
// SpeechRecognition
//
// Created by 李东 on 2017/8/22.
// Copyright © 2017年 LD. All rights reserved.
//
#import "SpeechRecognitionViewController.h"
#import <Speech/Speech.h>
#import <AVFoundation/AVFoundation.h>
@interface SpeechRecognitionViewController () <SFSpeechRecognizerDelegate>
//开始录音按钮
@property (weak, nonatomic) IBOutlet UIButton *recordButton;
//展示结果
@property (weak, nonatomic) IBOutlet UILabel *showResults;
//语音识别器
@property (nonatomic, strong) SFSpeechRecognizer *speechRecognizer;
// 语音识别任务,可监控识别进度。通过他可以取消或终止当前的语音识别任务
@property (nonatomic, strong) SFSpeechRecognitionTask *speechRecognitionTask;
// 语音引擎,负责提供录音输入
@property (nonatomic,strong) AVAudioEngine *audioEngine;
//从任意缓存中获取语音的识别请求
// 发起语音识别请求,为语音识别器指定一个音频输入源,这里是在音频缓冲器中提供的识别语音。
// SFSpeechAudioBufferRecognitionRequest 从任意缓存中获取语音的识别请求
// SFSpeechRecognitionRequest 从音频源识别语音的请求。
// SFSpeechURLRecognitionRequest 在录制的音频文件中识别语音的请求。
@property (nonatomic,strong) SFSpeechAudioBufferRecognitionRequest *recognitionRequest;
//语音合成器,负责文本转语音的播放
@property (nonatomic, strong) AVSpeechSynthesizer * avSS;
@end
@implementation SpeechRecognitionViewController
- (void)viewDidLoad {
[super viewDidLoad];
_recordButton.enabled = NO;
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//请求授权,使用的枚举
//SFSpeechRecognizerAuthorizationStatusNotDetermined : 语音识别未授权
//SFSpeechRecognizerAuthorizationStatusDenied :用户未授权使用语音识别
//SFSpeechRecognizerAuthorizationStatusRestricted :语音识别在这台设备上受到限制
//SFSpeechRecognizerAuthorizationStatusAuthorized :已授权
__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;
}
});
}];
}
//录音按钮点击方法
- (IBAction)recordButtonClick:(UIButton *)sender {
if (self.audioEngine.isRunning) {
// 停止录音
[self.audioEngine stop];
if (_recognitionRequest) {
[_recognitionRequest endAudio];
}
self.recordButton.enabled = NO;
[self.recordButton setTitle:@"正在停止。。。" forState: UIControlStateDisabled];
} else {
[self startRecording];
[self.recordButton setTitle:@"停止录音" forState:UIControlStateNormal];
}
}
//播放识别后的文本
- (IBAction)stratPlaySpeech:(id)sender {
[self readingAloudWithString:self.showResults.text language:@"zh-CN"];
}
//设置为扬声器播放
- (IBAction)setupeRceiver:(id)sender {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
}
//设置听筒播放
- (IBAction)setupSpeaker:(id)sender {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
}
//开始录音方法
- (void)startRecording {
//判断上一个任务是否还在,制空
if (_speechRecognitionTask) {
[_speechRecognitionTask cancel];
_speechRecognitionTask = nil;
}
//创建录音session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error;
//设置会话的类别,默认是听筒播放
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
//设置为扬声器播放
//[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
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;
_speechRecognitionTask = [self.speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
BOOL isFinall = NO;
if (result) {
//拿到全部的结果
// NSLog(@"%@", result);
// NSLog(@"%@", result.bestTranscription.formattedString);
//strongSelf.showResults.text = result.bestTranscription.formattedString;
//根据result.isFinal判断是不是最后的结果
isFinall = result.isFinal;
if (result.isFinal) {
NSLog(@"我是最后的结果");
strongSelf.showResults.text = result.bestTranscription.formattedString;
}
}
if (error || isFinall) {
[strongSelf.audioEngine stop];
[inputNode removeTapOnBus:0];
strongSelf.recognitionRequest = nil;
strongSelf.speechRecognitionTask = 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.showResults.text = @"正在录音。。。";
}
//使用系统的语音合成
- (void)readingAloudWithString:(NSString *)str language: (NSString *)language{
//说话的内容
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc] initWithString:str];
//语调0.5到2,默认1
utterance.pitchMultiplier = 1;
//语速 0到1,默认是0.5
utterance.rate = 0.5;
//音量
utterance.volume = 1;
AVSpeechSynthesisVoice *voiceType = [AVSpeechSynthesisVoice voiceWithLanguage:language];
utterance.voice = voiceType;
[self.avSS speakUtterance:utterance];
}
#pragma mark - 懒加载
//语音合成器
- (AVSpeechSynthesizer *)avSS {
if (!_avSS) {
_avSS = [[AVSpeechSynthesizer alloc] init];
_avSS.delegate = self;
}
return _avSS;
}
//语音引擎,负责提供录音输入
- (AVAudioEngine *)audioEngine {
if (!_audioEngine) {
_audioEngine = [[AVAudioEngine alloc] init];
}
return _audioEngine;
}
//懒加载语音识别器
- (SFSpeechRecognizer *)speechRecognizer {
if (!_speechRecognizer) {
//为识别语音设置语言这里暂时设置为中文
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh-CN"];
_speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
_speechRecognizer.delegate = self;
}
return _speechRecognizer;
}
#pragma mark - SFSpeechRecognizerDelegate
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available {
if (available) {
self.recordButton.enabled = YES;
[self.recordButton setTitle:@"开始录音" forState: UIControlStateNormal];
} else {
self.recordButton.enabled = NO;
[self.recordButton setTitle:@"语音识别不可用" forState:UIControlStateDisabled];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
网友评论