iOS语音合成,语音阅读《AVFoundation》->AVSpeechSynthesizer使用方法介绍

效果图,图片找的网上的

一:写在前面

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 现在的天空很美。 邃蓝色的天空,晴空万里。虽已是傍晚,云朵看上去依然轻透,它的白和天空的蓝勾勒出清...
    雪熙snowie阅读 273评论 0 1
  • NSPredicate可以支持数据库查询,平时的一些数组查询之类也用这个方法,以下是一些总结 格式字符串的一些基本...
    Liberalism阅读 1,991评论 2 1
  • 今天又是星期六,早晨我走的时候,小家伙刚刚醒,我说你在睡一会吧,等奶奶起来,你在起来,不行,非要起床,我说行...
    耿浩然妈妈阅读 277评论 0 3
  • 宝贝露露2016到了陪你度过的第二个生日虽然在远方陪你过当你不要失望这个礼物还是很丰富的 等你回来一起到处玩我们的...
    a煜阅读 242评论 0 0