前言
为了满足需求, 关爱老年人, 在文章详情页添加字体放大缩小功能之后, 又要增加语音报告功能。在中国人口老年化的大背景下, 总结 iOS 语音播报功能, 写下了这篇文章。
正文
文本转语音技术, 也叫TTS, 是Text To Speech的缩写.
一、语音播报相关属性介绍
内容文本转语音播报, 需要使用到AVFoundation框架中的 AVSpeechSynthesizer 和 AVSpeechUtterance 这两个关键类。
// 合成器 控制播放,暂停
@property(nonatomic,strong) AVSpeechSynthesizer * synthesizerAV;
// 实例化发声的对象,及朗读的内容,可以控制说话的语速 等
@property(nonatomic,strong) AVSpeechUtterance *utterance;
按住command点击AVSpeechSynthesizer可以看到
//将发声的对象添加到合成器队列中, 开始语音播报
- (void)speakUtterance:(AVSpeechUtterance *)utterance;
//停止结束语音播报
- (BOOL)stopSpeakingAtBoundary:(AVSpeechBoundary)boundary;
//暂停语音播报
- (BOOL)pauseSpeakingAtBoundary:(AVSpeechBoundary)boundary;
//继续语音播报
- (BOOL)continueSpeaking;
AVSpeechSynthesizerDelegate代理方法
#pragma mark - AVSpeechSynthesizerDelegate
//已经开始
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
}
//已经说完
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
//如果朗读要循环朗读,可以在这里再次调用朗读方法
//[_avSpeaker speakUtterance: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{
}
按住command点击AVSpeechSynthesizer可以看到
//实例化发声的对象,设置需要发声内容
+ (instancetype)speechUtteranceWithString:(NSString *)string;
//设置合成语音的语言 defaults to your system language
@property(nonatomic, retain, nullable) AVSpeechSynthesisVoice *voice;
//设置语速 0.0f~1.0f
//Values are pinned between AVSpeechUtteranceMinimumSpeechRate and AVSpeechUtteranceMaximumSpeechRate.
@property(nonatomic) float rate;
//声音的音调 0.5f~2.0f [0.5 - 2] Default = 1
@property(nonatomic) float pitchMultiplier;
//设置朗读的音量 [0-1] Default = 1
@property(nonatomic) float volume;
语言种类 : Language
ar-SA 沙特阿拉伯(阿拉伯文)
en-ZA, 南非(英文)
nl-BE, 比利时(荷兰文)
en-AU, 澳大利亚(英文)
th-TH, 泰国(泰文)
de-DE, 德国(德文)
en-US, 美国(英文)
pt-BR, 巴西(葡萄牙文)
pl-PL, 波兰(波兰文)
en-IE, 爱尔兰(英文)
el-GR, 希腊(希腊文)
id-ID, 印度尼西亚(印度尼西亚文)
sv-SE, 瑞典(瑞典文)
tr-TR, 土耳其(土耳其文)
pt-PT, 葡萄牙(葡萄牙文)
ja-JP, 日本(日文)
ko-KR, 南朝鲜(朝鲜文)
hu-HU, 匈牙利(匈牙利文)
cs-CZ, 捷克共和国(捷克文)
da-DK, 丹麦(丹麦文)
es-MX, 墨西哥(西班牙文)
fr-CA, 加拿大(法文)
nl-NL, 荷兰(荷兰文)
fi-FI, 芬兰(芬兰文)
es-ES, 西班牙(西班牙文)
it-IT, 意大利(意大利文)
he-IL, 以色列(希伯莱文,阿拉伯文)
no-NO, 挪威(挪威文)
ro-RO, 罗马尼亚(罗马尼亚文)
zh-HK, 香港(中文)
zh-TW, 台湾(中文)
sk-SK, 斯洛伐克(斯洛伐克文)
zh-CN, 中国(中文)
ru-RU, 俄罗斯(俄文)
en-GB, 英国(英文)
fr-FR, 法国(法文)
hi-IN 印度(印度文)
二、文章详情H5界面内容语音播报使用
①添加框架, 导入头文件, 设置代理
导入头文件
#import<AVFoundation/AVFoundation.h>
设置代理(非必需设置项,看需求)
@interface ViewController ()<AVSpeechSynthesizerDelegate>
②创建对象
// 合成器 控制播放,暂停
@property(nonatomic,strong) AVSpeechSynthesizer * synthesizerAV;
// 实例化发声的对象,及朗读的内容,可以控制说话的语速 等
@property(nonatomic,strong) AVSpeechUtterance *utterance;
这地方模拟H5界面文章详情内容
//模拟服务器返回数据
NSString *content = @"<p> 日前,湖北邮政公司党组对全省邮政企业30个红旗支局党支部开展了示范引领“回头看”检查,检查指标涉及党员“三亮”载体覆盖率、业务收入增幅等10项党建工作及经营管理指标。检查结果显示,全省邮政企业30个红旗党支部示范引领作用十分明显,主要表现为三个方面:一是党建工作真正落地。全省邮政企业30个红旗支局党支部扎实开展了“三亮三比三创”活动,充分发挥了党员的先锋模范作用,党员劳动竞赛完成率均在100%以上,党员“三亮”载体覆盖率均为100%。同时,各支部明确了特色支部的建设方向,加强了党员队伍建设。二是业务收入快速增长。全省邮政企业30个红旗支局党支部所在支局共实现业务收入2。15亿元,净增业务收入2660万元,平均增幅16。5%,其中武汉市江夏区城关支局党支部所在支局业务收入增幅达46%、荆门市沙洋县沈集支局党支部所在支局业务收入增幅达37。95%、孝感市肖港支局党支部所在支局业务收入增幅达30。2%,收入增长势头喜人;人均劳动生产率达到37。26万元,其中孝感市三汊支局党支部、胡金店支局党支部、肖港支局党支部所在支局劳动生产率分别达到59万元、58。4万元、57。5万元,业绩表现突出。三是储蓄余额规模快速扩张。全省邮政企业30个红旗支局党支部所在支局累计储蓄余额规模达到198。49亿元,1-7月份新增储蓄余额过亿的有11个支局,其中武汉市韩家墩支局党支部、钟家村支局党支部以及青山区钢花支局党支部所在支局新增储蓄余额分别达到4。89亿元、2。51亿元和2。12亿元,储蓄余额增长势头强劲。<br></p>";
//去除HTML标签处理
NSString *contentStr = [self filterHTML:content];
//将Unicode转变为字符串时"."->"。",需要替换字符
NSString *contentString = [contentStr stringByReplacingOccurrencesOfString:@"。" withString:@"."];
在服务器返回的内容content中有HTML标签需要去除,使用下面方法 :
//处理HTML标签
-(NSString *)filterHTML:(NSString *)html
{
NSScanner * scanner = [NSScanner scannerWithString:html];
NSString * text = nil;
while([scanner isAtEnd]==NO)
{
[scanner scanUpToString:@"<" intoString:nil];
[scanner scanUpToString:@">" intoString:&text];
html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
}
return html;
}
创建语音播报对象
_synthesizerAV = [[AVSpeechSynthesizer alloc] init];
_utterance = [AVSpeechUtterance speechUtteranceWithString:contentString];
③设置相关属性
// 语速 0.0f~1.0f AVSpeechUtteranceMaximumSpeechRate / 4.0f;
_utterance.rate = 0.45f;
// 声音的音调 0.5f~2.0f
_utterance.pitchMultiplier = 0.8f;
//设置合成语音的语言 defaults to your system language zh-TW zh-CN
_utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
//设置朗读的音量 [0-1] Default = 1
_utterance.volume = 0.8;
④开始、暂停/继续、结束
开始文章内容朗读播报
[_synthesizerAV speakUtterance:_utterance];
暂停朗读播报
//暂停朗读
//AVSpeechBoundaryImmediate 立即停止
//AVSpeechBoundaryWord 当前词结束后停止
[_synthesizerAV pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
继续朗读播报
[_synthesizerAV continueSpeaking];
结束朗读播报
//AVSpeechBoundaryImmediate 立即停止
//AVSpeechBoundaryWord 当前词结束后停止
[_synthesizerAV stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
⑤实现后台播放
1.在配置里设置
2.在AppDelegate.m里添加代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error = nil;
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
[session setActive:YES error:&error];
[Bmob registerWithAppKey:BMOB_AppID];
return YES;
}
小知识点
iOS7之后才有该功能, 不过现在Xcode 8最低支持就是iOS 8.0了。
后记
除了选择系统的语音播报, 当然你还可以选择讯飞的文字转语音技术,不过它受网络的影响比较大,而且离线转语音价格比较贵,最便宜的要8000RMB/2000装机量。
还有一种是使用 百度语音SDK
①下载离在线合成语音包
②记住这3个key
③查看官方示例Demo, 实现播放和设置声音代码
-(void)configureSDK{
NSLog(@"TTS version info: %@", [BDSSpeechSynthesizer version]);
[BDSSpeechSynthesizer setLogLevel:BDS_PUBLIC_LOG_VERBOSE];
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
[self configureOnlineTTS];
[self configureOfflineTTS];
}
// 配置在线
-(void)configureOnlineTTS{
//#error "Set api key and secret key"
[[BDSSpeechSynthesizer sharedInstance] setApiKey:@"e7QA3FWob8EbzLDP7I6fCtcY" withSecretKey:@"17d90e1974d0bcb31725245f96718e73"];
}
// 配置离线
-(void)configureOfflineTTS{
NSString offlineEngineSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_Speech_Female" ofType:@"dat"];
NSString offlineEngineTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_Text" ofType:@"dat"];
NSString offlineEngineEnglishSpeechData = [[NSBundle mainBundle] pathForResource:@"English_Speech_Female" ofType:@"dat"];
NSString offlineEngineEnglishTextData = [[NSBundle mainBundle] pathForResource:@"English_Text" ofType:@"dat"];
NSString offlineEngineLicenseFile = [[NSBundle mainBundle] pathForResource:@"offline_engine_tmp_license" ofType:@"dat"];
//#error "set offline engine license"
NSError err = [[BDSSpeechSynthesizer sharedInstance] loadOfflineEngine:offlineEngineTextData speechDataPath:offlineEngineSpeechData licenseFilePath:offlineEngineLicenseFile withAppCode:@"9353239"]; //
if (err) {
return;
}
err = [[BDSSpeechSynthesizer sharedInstance] loadEnglishDataForOfflineEngine:offlineEngineEnglishTextData speechData:offlineEngineEnglishSpeechData];
if (err) {
return;
}
}
// 播放失败
-(void)synthesizerErrorOccurred:(NSError *)error speaking:(NSInteger)SpeakSentence synthesizing:(NSInteger)SynthesizeSentence{
[[BDSSpeechSynthesizer sharedInstance] cancel];
}
// 合成参数设置
// 声音
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:BDS_SYNTHESIZER_SPEAKER_FEMALE] forKey:BDS_SYNTHESIZER_PARAM_SPEAKER ];
// 音量
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_VOLUME];
// 音速
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_SPEED];
// 音调
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_PITCH];
// 压缩
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt: BDS_SYNTHESIZER_AUDIO_ENCODE_MP3_16K] forKey:BDS_SYNTHESIZER_PARAM_AUDIO_ENCODING ];
我是楚简约,感谢您的阅读,
喜欢就点个赞呗,“❤喜欢”,
鼓励一下,你在看,我就继续写~
非简书用户,可以点右上角的三个“...”,然后"在Safari中打开”,就可以点赞咯~