iOS,系统语音合成语音识别

发布时间 2023-11-09 10:23:53作者: 帅不过三秒

1.系统语音合成语音识别

#import "ViewController.h"
//导入语音合成系统库
#import <AVFoundation/AVFoundation.h>
//导入语音识别系统库
#import <Speech/Speech.h>

@interface ViewController ()<AVSpeechSynthesizerDelegate,SFSpeechRecognitionTaskDelegate,NFCTagReaderSessionDelegate>
@property (nonatomic, strong) AVSpeechSynthesizer *synthesizer;//语音合成iOS7开始支持

//iOS语音识别
@property (nonatomic, strong) SFSpeechRecognizer *speechRecognizer;
@property (nonatomic, strong) AVAudioEngine *audioEngine;
@property (nonatomic, strong) SFSpeechAudioBufferRecognitionRequest *recognitionRequest;

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) UIButton *recordBtn;
@property (nonatomic, assign) BOOL isRecord;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view setBackgroundColor:[UIColor whiteColor]];
    float left=20;
    self.textView=[[UITextView alloc] initWithFrame:CGRectMake(15, 44, self.view.frame.size.width-30, 120)];
    self.textView.text=@"iOS7新特性,语音合成测试用例";
    self.textView.textColor=[UIColor blackColor];
    self.textView.font=[UIFont systemFontOfSize:16.0f];
    self.textView.layer.borderWidth=1.0f;
    self.textView.layer.borderColor=[UIColor grayColor].CGColor;
    [self.view addSubview:self.textView];
    
    UIButton *goBtn=[[UIButton alloc] initWithFrame:CGRectMake(left, self.textView.frame.origin.y+self.textView.frame.size.height+10, self.view.frame.size.width-2*left, 50)];
    [goBtn setTitle:@"合成播放" forState:UIControlStateNormal];
    [goBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [goBtn setBackgroundColor:[UIColor grayColor]];
    [goBtn addTarget:self action:@selector(speakAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:goBtn];
    
    self.recordBtn=[[UIButton alloc] initWithFrame:CGRectMake(left, goBtn.frame.origin.y+goBtn.frame.size.height+10, self.view.frame.size.width-2*left, 50)];
    [self.recordBtn setTitle:@"录制识别" forState:UIControlStateNormal];
    [self.recordBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self.recordBtn setBackgroundColor:[UIColor grayColor]];
    [self.recordBtn addTarget:self action:@selector(recordAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.recordBtn];
    self.isRecord=NO;
}

//结束触摸
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    //isExclusiveTouch一个布尔值来指示接收机处理触摸事件。
    //没有触摸_textUser进入if内操作
    if (![self.textView isExclusiveTouch]) {
        //resignFirstResponder取消第一响应者状态的。如果对textfield使用的话,那么调用这个方法,textfield的第一响应者状态就会取消,然后键盘就消失了。
        [self.textView resignFirstResponder];
    }
}


-(void)recordAction{
    
    if (self.isRecord) {
        self.isRecord=NO;
        [self stopRecording];
        [self.recordBtn setTitle:@"录制识别" forState:UIControlStateNormal];
    }else{
        [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
            NSLog(@"status %@", status == SFSpeechRecognizerAuthorizationStatusAuthorized ? @"授权成功" : @"授权失败");
            dispatch_async(dispatch_get_main_queue(), ^{
                if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
                    [self startRecording];
        //            //block回调方式
        //            [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
        //
        //                    if (result.isFinal) {
        //                        NSLog(@"is final: %d  result: %@", result.isFinal, result.bestTranscription.formattedString);
        //                    }
        //            }];
                    self.isRecord=YES;
                    [self.recordBtn setTitle:@"停止录制" forState:UIControlStateNormal];
                    //delegate回调方式
                    [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest delegate:self];
                }else{
                    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"没有语音识别权限" preferredStyle:UIAlertControllerStyleAlert];
                    
                    // 2.创建并添加按钮
                    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"暂不授权" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

                    }];
                    [alertController addAction:cancelAction];
                    
                    // 2.创建并添加按钮
                    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"去授权" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                            #ifdef __IPHONE_8_0
                            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                            if ([[UIApplication sharedApplication]canOpenURL:url]) {
                                [[UIApplication sharedApplication]openURL:url];
                            }
                            #endif
                    }];
                    [alertController addAction:okAction];
                    [self presentViewController:alertController animated:YES completion:nil];
                }
            });

        }];
    }
    
}

-(void)speakAction{
    [self speakString:self.textView.text];
}



-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    
    // 请求识别权限info.plist
//    <key>NSSpeechRecognitionUsageDescription</key>
//    <string>请允许语音识别</string>
//    <key>NSMicrophoneUsageDescription</key>
//    <string>请允许麦克风</string>
    

    
    return;
    
  
}

- (void)initEngine {
    if (!self.speechRecognizer) {
        // 设置语言
        NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"zh-CN"];
        self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
    }
    if (!self.audioEngine) {
        self.audioEngine = [[AVAudioEngine alloc] init];
    }
    
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryRecord mode:AVAudioSessionModeMeasurement options:AVAudioSessionCategoryOptionDuckOthers error:nil];
    [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
    
    if (self.recognitionRequest) {
        [self.recognitionRequest endAudio];
        self.recognitionRequest = nil;
    }
    self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
    self.recognitionRequest.shouldReportPartialResults = YES;
}
- (void)startRecording{
    [self initEngine];
    
    AVAudioFormat *recordingFormat = [[self.audioEngine inputNode] outputFormatForBus:0];
    [[self.audioEngine inputNode] installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
        [self.recognitionRequest appendAudioPCMBuffer:buffer];
    }];
    [self.audioEngine prepare];
    [self.audioEngine startAndReturnError:nil];
    
}

- (void)stopRecording{
    [[self.audioEngine inputNode] removeTapOnBus:0];
    [self.audioEngine stop];
    [self.recognitionRequest endAudio];
    self.recognitionRequest = nil;
}


-(void)speakString:(NSString *)string{
    //避免手机静音合成语音不能播放
    NSError *setCategoryErr = nil;
    NSError *activationErr = nil;
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
    //magic is here
    [[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
    
    //语音合成
      //设置语言类别( 不能被识别,返回值为nil)
    AVSpeechSynthesisVoice *voiceType = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
    AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:string];
    utterance.voice =  voiceType;
    utterance.rate *=1.0;//设置语速
    utterance.volume =1.0;//设置音量
    [self.synthesizer speakUtterance:utterance];
}

#pragma mark  SFSpeechRecognitionTaskDelegate
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (recognitionResult.isFinal) {
            NSLog(@"is final: %d  result: %@", recognitionResult.isFinal, recognitionResult.bestTranscription.formattedString);
            self.textView.text=recognitionResult.bestTranscription.formattedString;
        }else{
            self.textView.text=@"识别失败";
        }
    });

}
#pragma mark AVSpeechSynthesizerDelegate
-(void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{

NSLog(@"语音合成开始");

}

-(void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{

NSLog(@"语音合成完成");

}

#pragma mark lazyloading
/**
 @author Vie 2022年06月23日15:11:43
 @初始化懒加载alertTipView
 @return alertTipView
 */
-(AVSpeechSynthesizer *)synthesizer{
    if (!_synthesizer) {
        //语音合成
        // 语音合成器会生成音频
        _synthesizer = [[AVSpeechSynthesizer alloc] init];
        _synthesizer.delegate=self;
    }
    return _synthesizer;
}
@end