美文网首页
使用iOS语言识别以及语言合成遇到的坑

使用iOS语言识别以及语言合成遇到的坑

作者: 小驴拉磨 | 来源:发表于2017-08-30 18:02 被阅读349次

    语音识别

    坑一、授权的几个枚举一定要注意千万别写错了,细心点莫有问题!!

    语音合成

    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
    

    详细的语音合成下篇文章给大家介绍,有问题希望大家积极留言,刚刚加入简书,希望大家多多支持。dmeo地址就不留了,整个代码复制就能运行。

    相关文章

      网友评论

          本文标题:使用iOS语言识别以及语言合成遇到的坑

          本文链接:https://www.haomeiwen.com/subject/vnkxjxtx.html