美文网首页直播音视频专辑音视频
iOS语音合成,语音阅读《AVFoundation》->A

iOS语音合成,语音阅读《AVFoundation》->A

作者: 张芳涛 | 来源:发表于2018-03-06 16:54 被阅读72次
    效果图,图片找的网上的

    一:写在前面

    相关源代码已经上传到网上,里面该有的注释也都有了,感兴趣的同学可以直接上Github下载: AVFoundation相关代码下载地址:点击我就可以了

    二:正文

    我们有时候在读书软件上可以发现语音朗读功能(读起来好像没什么感情)。其实这个利用iOS系统api就可以实现。下面就通过一个语音朗读文字的demo来讲解该功能的实现步骤。

    2.1:AVSpeechSynthesizer介绍

    实现该功能核心的部件就是AVSpeechSynthesizer。

    NS_CLASS_AVAILABLE_IOS(7_0)
    @interface AVSpeechSynthesizer : NSObject
    

    大家看到了么,iOS7.0之后才出现了AVSpeechSynthesizer。AVSpeechSynthesizer具有以下属性:

    //代理方法
    @property(nonatomic, weak, nullable) id<AVSpeechSynthesizerDelegate> delegate;
    //是否正在朗读(只读)
    @property(nonatomic, readonly, getter=isSpeaking) BOOL speaking;
    //是否已经暂停(只读)
    @property(nonatomic, readonly, getter=isPaused) BOOL paused;
    

    支持的方法如下:

    //朗读方法,需要一个AVSpeechUtterance类型参数
    - (void)speakUtterance:(AVSpeechUtterance *)utterance;
    
    //停止朗读,会清理掉当前正在执行朗读操作的队列    
    - (BOOL)stopSpeakingAtBoundary:(AVSpeechBoundary)boundary;
    //暂停朗读,这里面需要传递一个AVSpeechBoundary类型参数,两种选择,是立即停止还是读完这个单词再停止。
    - (BOOL)pauseSpeakingAtBoundary:(AVSpeechBoundary)boundary;
    //继续朗读
    - (BOOL)continueSpeaking;
    

    上面提到代理方法,还记得不?下面就是相关的代理方法:

    //开始朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance;
    //结束朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance;
    //暂停朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance;
    //继续朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance;
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance;
    ////将要播放的语音文字代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance;
    

    2.2:AVSpeechUtterance介绍

    除了核心的AVSpeechSynthesizer,还有一个非常关键的成员就是AVSpeechUtterance,要是想把声音读出来并且设置和声音有关的一些属性,你离不开它。AVSpeechUtterance主要包含以下属性:

    //需要用什么语言来朗读,系统提供了很多语言选项,如果有中文,一定要选择中文语言,要不然读不出来。
    @property(nonatomic, retain, nullable) AVSpeechSynthesisVoice *voice;
    //朗读的内容
    @property(nonatomic, readonly) NSString *speechString;
    //朗读的内容NSAttributedString 格式
    @property(nonatomic, readonly) NSAttributedString *attributedSpeechString API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
    
    /* Setting these values after a speech utterance has been enqueued will have no effect. */
    ////语速0.0f~1.0f
    @property(nonatomic) float rate;             // Values are pinned between AVSpeechUtteranceMinimumSpeechRate and AVSpeechUtteranceMaximumSpeechRate.
     //声音的音调0.5f~2.0f
    @property(nonatomic) float pitchMultiplier;  // [0.5 - 2] Default = 1
    @property(nonatomic) float volume;           // [0-1] Default = 1
    //播放下下一句话的时候有多长时间的延迟
    @property(nonatomic) NSTimeInterval preUtteranceDelay;    // Default is 0.0
    //开始播放之前需要等待多久
    @property(nonatomic) NSTimeInterval postUtteranceDelay;   // Default is 0.0
    

    支持的方法如下:

    //初始化类方法,需要传一个字符串进去
    + (instancetype)speechUtteranceWithString:(NSString *)string;
     //初始化类方法,需要一个NSAttributedString类型字符串
    + (instancetype)speechUtteranceWithAttributedString:(NSAttributedString *)string API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
    
    //初始化对象方法,需要一个字符串作为参数
    - (instancetype)initWithString:(NSString *)string;
    //初始化对象方法,需要一个NSAttributedString类型字符串
    - (instancetype)initWithAttributedString:(NSAttributedString *)string API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
    

    上面提到的语言类型,主要由以下几种:

    Arabic (ar-SA)
    Chinese (zh-CN, zh-HK, zh-TW)
    Czech (cs-CZ)
    Danish (da-DK)
    Dutch (nl-BE, nl-NL)
    English (en-AU, en-GB, en-IE, en-US, en-ZA)
    Finnish (fi-FI)
    French (fr-CA, fr-FR)
    German (de-DE)
    Greek (el-GR)
    Hebrew (he-IL)
    Hindi (hi-IN)
    Hungarian (hu-HU)
    Indonesian (id-ID)
    Italian (it-IT)
    Japanese (ja-JP)
    Korean (ko-KR)
    Norwegian (no-NO)
    Polish (pl-PL)
    Portuguese (pt-BR, pt-PT)
    Romanian (ro-RO)
    Russian (ru-RU)
    Slovak (sk-SK)
    Spanish (es-ES, es-MX)
    Swedish (sv-SE)
    Thai (th-TH)
    Turkish (tr-TR)
    

    三:代码实现:

    相关知识点介绍完毕之后,下面就是具体的代码实现:

    #import "ViewController.h"
    #import <AVFoundation/AVFoundation.h>
    @interface ViewController ()<AVSpeechSynthesizerDelegate>
    @property(nonatomic,strong) NSArray * strArray;
    @property(nonatomic,strong) NSArray *voiceArray;
    @property(nonatomic,strong) AVSpeechSynthesizer *synthesizer;
    @property (weak, nonatomic) IBOutlet UILabel *speechLabel;
    @property (weak, nonatomic) IBOutlet UIButton *controlButton;
    @property (nonatomic,assign)BOOL isPlay;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.strArray =@[@"单车欲问边,",
                     @"属国过居延。",
                     @"征蓬出汉塞,",
                     @"归雁入胡天。",
                     @"大漠孤烟直,",
                     @"长河落日圆,",
                     @"萧关逢候骑,",
                     @"都护在燕然。",
                     @"A solitary carriage to the frontiers bound,",
                     @"An envoy with no retinue around,",
                     @"A drifting leaf from proud Cathy,",
                     @"With geese back north on a hordish day.",
                     @"A smoke hangs straight on the desert vast,",
                     @"A sun sits round on the endless stream.",
                     @"A horseman bows by a fortress passed:",
                     @"The general’s at the north extreme!"];
    self.voiceArray = @[[AVSpeechSynthesisVoice voiceWithLanguage:@"en-GB"],[AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]];
    self.synthesizer = [[AVSpeechSynthesizer alloc]init];
    self.isPlay = NO;
    [self.controlButton setTitle:@"pause" forState:UIControlStateNormal];
    self.synthesizer.delegate = self;
    for (int i = 0; i < self.strArray.count;  i ++) {
        AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:self.strArray[i]];
        //需要读的语言
        if (i < 8) {
            utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
        }
        else{
            utterance.voice = self.voiceArray[i%2];
        }
        //语速0.0f~1.0f
        utterance.rate = 0.5f;
        //声音的音调0.5f~2.0f
        utterance.pitchMultiplier = 0.8f;
        //播放下下一句话的时候有多长时间的延迟
        utterance.postUtteranceDelay = 0.1f;
        //上一句之前需要多久
        utterance.preUtteranceDelay = 0.5f;
        //音量
        utterance.volume = 1.0f;
        //开始播放
        [self.synthesizer speakUtterance:utterance];
    }
    }
    //开始朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"didStartSpeechUtterance->%@",utterance.speechString);
    }
    //结束朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"didFinishSpeechUtterance->%@",utterance.speechString);    
    }
    //暂停朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"didPauseSpeechUtterance->%@",utterance.speechString);
    }
    //继续朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"didContinueSpeechUtterance->%@",utterance.speechString);
    }
    //取消朗读的代理方法
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"didCancelSpeechUtterance->%@",utterance.speechString);
    }
    //将要播放的语音文字
    - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{
    NSLog(@"willSpeakRangeOfSpeechString->characterRange.location = %zd->characterRange.length = %zd->utterance.speechString= %@",characterRange.location,characterRange.length,utterance.speechString);
    self.speechLabel.text = utterance.speechString;
    }
    
    - (IBAction)buttonClick:(id)sender {
    self.isPlay = !self.isPlay;
    if (self.isPlay) {
     [self.controlButton setTitle:@"play" forState:UIControlStateNormal];
        [self.synthesizer  pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
    }
    else{
     [self.controlButton setTitle:@"pause" forState:UIControlStateNormal];
        [self.synthesizer continueSpeaking];
    }
    }
    
    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }
    
    
    @end
    

    写在后面:

    相关源代码已经上传到网上,里面该有的注释也都有了,感兴趣的同学可以直接上Github下载: AVFoundation相关代码下载地址:点击我就可以了

    相关文章

      网友评论

        本文标题:iOS语音合成,语音阅读《AVFoundation》->A

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