这里要说的是iOS的语音合成工具
FKTTSManager
的优化第二版,在上一集关于FKTTSManager
的文章中,本人介绍了AVSpeechSynthesizer,这是iOS原生自带的TTS(Text To Speech)工具。该工具具有自定义语速,音量的功能,但在音色方面的设置比较死板,只能设置音调,很多用户反馈语音播报的音色实在是难听,所以博主我决定去了解一下其他公司制作的语音合成方案,因此了解了一下百度,讯飞,云之声,最后博主选择接入百度语音合成功能,因为百度语音合成免费集成,并且支持离线播放。如果有兴趣的朋友也可以了解一下讯飞和云之声。好吧,下面我们来唠嗑一下集成百度语音合成SDK的故事。
百度语音合成
百度语音合成技术能将用户输入的文字,转换成流畅自然的语音输出,并且可以支持语速、音调、音量、音频码率设置,打破传统文字式人机交互的方式,让人机沟通更自然。
百度语音合成的介绍页
百度语音合成Demo下载
在这篇博客中,我会简要的介绍一下百度语音合成集成的注意事项和功能要点,想要了解更详细的朋友可以打开上方的链接,下载百度的Demo运行一下。
集成注意点
集成百度语音合成SDK需要向工程里引入以下库
博主截图比官网技术文档给的引入库截图相比,多了几个库,但是多的几个库也是必要的,因为在集成过程中发现只有把上图中所有库都引入才能正常运行整个工程,否则会报错。
1.配置 API Key 和 Secret Key
// 设置apiKey和secretKey
[[BDSSpeechSynthesizer sharedInstance] setApiKey:@"your API key" withSecretKey:@"your secret key"];
API Key 和 Secret Key 需要开发者申请百度帐号,到百度AI开放平台自己注册应用,申请。每一个注册的应用对应一个API Key 和 Secret Key,也是应用在百度平台上的唯一标识符。
2.设置代理方法
// 设置委托对象
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
BDSSpeechSynthesizer
也有自己的代理方法,配置以上代码后,语音播放会走响应的代码方法。
//开始合成
- (void)synthesizerStartWorkingSentence:(NSInteger)SynthesizeSentence
{
NSLog(@"Began synthesizing sentence %ld", (long)SynthesizeSentence);
}
//结束合成
- (void)synthesizerFinishWorkingSentence:(NSInteger)SynthesizeSentence
{
NSLog(@"Finished synthesizing sentence %ld", (long)SynthesizeSentence);
}
//开始播放
- (void)synthesizerSpeechStartSentence:(NSInteger)SpeakSentence
{
NSLog(@"Began playing sentence %ld", (long)SpeakSentence);
}
//结束播放
- (void)synthesizerSpeechEndSentence:(NSInteger)SpeakSentence
{
NSLog(@"Finished playing sentence %ld", (long)SpeakSentence);
}
3.设置离线引擎
百度语音合成采用的离在线融合技术,可以根据当前网络环境自动判断本地引擎或云端引擎,进行合成。
也就是说百度语音支持离线语音播放功能,离线播放功能也正是博主正要完成的一项非常重要的功能,所以了解到百度能够支持离线播放后,博主果断的选择接入百度语音。
// 设置离线引擎
NSString *ChineseSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_Speech_Female" ofType:@"dat"];
NSString *ChineseTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_text" ofType:@"dat"];
NSString *LicenseData = [[NSBundle mainBundle] pathForResource:@"bdtts_license" ofType:@"dat"];
NSError* loadErr = [[BDSSpeechSynthesizer sharedInstance] startTTSEngine:ChineseTextData speechDataPath:ChineseSpeechData
licenseFilePath:LicenseData withAppCode:@"Your APPID"];
注意:
开发者在百度AI管理平台申请应用时,会设置一个包名信息,这个包名信息需要使用项目工程的BundleId。所以在代码中配置apiKey、secretKey、APPID时,一定要使用对应包名下对应的apiKey、secretKey、APPID,这样才能配置成功。
并且经过本人的测试,离线播放功能只能适用于真机上,模拟器上会播放失败。
4.指定文案合成语音播放
// 开始合成并播放
NSError* speakError = nil;
if([[BDSSpeechSynthesizer sharedInstance] speakSentence:@"您想说的话请输入在这里" withError:&speakError] == -1){
// 错误
NSLog("错误: %ld, %@", (long)speakError.code, speakError.localizedDescription);
}
通过speakSentence方法开始语音的合成和播放,speakSentence还会返回一个错误信息,如果返回为空则说明文案合成播放成功。
FKTTSManager (结合百度语音合成版)
因为需求方对音色的要求,FKTTSManager集成了百度语音SDK,集成了SDK后,语音合成播放会优先使用百度语音合成,在百度语音合成失败的情况下,自动无缝转换到AVSpeechSynthesis,进行iOS原生的语音合成播放。
FKTTSManager(百度语音合成版)下载
想要使用FKTTSManager,向工程中引入demo中的FKTTSManager文件夹就可以了。新版的FKTTSManager中增加了BDSSpeechManager
类。
BDSSpeechManager中开放了几个方法。
/**配置百度ai*/
- (void)configureBaiDuSDk;
/**朗读谋一段*/
- (void)configureReadStr:(NSString*)readStr;
- (void)pauseSpeak;
- (void)continueSpeak;
- (void)stopSpeak;
Demo是优先使用百度语音合成,在百度语音失败的情况下无缝切换原生语音合成,所以我的播放功能的按钮的响应事件如下:
//开始
- (IBAction)startRead:(id)sender {
[[BDSSpeechManager shareManager] configureReadStr:self.readTextV.text];
}
//暂停
- (IBAction)pauseRead:(id)sender {
[[BDSSpeechManager shareManager] pauseSpeak];
}
//继续
- (IBAction)continueRead:(id)sender {
[[BDSSpeechManager shareManager] continueSpeak];
}
//停止
- (IBAction)stopRead:(id)sender {
[[BDSSpeechManager shareManager] stopSpeak];
}
百度语音合成播放值得注意的位置
百度语音合成播放的文字段落存在字数限制,每次在线合成播放的最大有效字数为350字,多余这个字数会出现合成失败,播放失败的问题。所以博主的策略是将大段文字通过300字(也可以是别的字数)为一段进行截取,保存至数组中,第一次播放时播放数组中第一段,然后监控播放结束的代理方法,代理方法执行后继续播放数组中的下一段,达成可以连续播放大段文字的效果。
/**播放文本长度大于300的文本格式(正常完整的播放最大支持340个字)*/
- (void)playLongStr:(NSString*)longStr {
longStr = [longStr stringReplaceEmoji:longStr];
longStr = [longStr stringByReplacingOccurrencesOfString:@"\n" withTheString:@""];
longStr = [NSString formatToLinefeedWith:longStr insertPosition:300];
NSArray *readStrArr = [[longStr componentsSeparatedByString:@"\n"] copy];
for (NSString *str in readStrArr) {
if (str.length != 0) {
[self.readStrArrM addObject:str];
}
}
[self playReadStr:[self.readStrArrM firstObject]];
}
/**结束播放*/
- (void)synthesizerSpeechEndSentence:(NSInteger)SpeakSentence {
//NSLog(@"播放结束a ");
if (self.readStrArrM.count > 0) {
[self.readStrArrM removeObjectAtIndex:0];
if (self.readStrArrM.count > 0) {
[self playReadStr:[self.readStrArrM firstObject]];
}
else {
[self stopSpeak];
}
}
else {
[self stopSpeak];
}
}
结尾
因为百度语音合成的音色更佳柔和一些,并且支持4种音色选择,所以博主选择接入它。但百度语音合成也存在短板,比如每次播放存在字数限制,离线播放时的音色会不及在线播放的好听,并且播放成功率上也不稳定,博主有一次有那么一段话使用百度语音怎么都无法播放,后来发现是因为那段话中存在emoji表情符,在文字截断成数组的过程中,有表情符被截断了,因此百度语音合成失败,但iOS原生的语音合成最后合成成功,因此得出iOS原生播放的成功率会比百度高的结论。如今FKTTSManager将百度语音合成和原生语音合成结合在一起,在提高产品体验的同时,也保证了功能的稳定性,可以说是一个很好的方案。有兴趣的朋友可以通过下面的链接下载Demo了解以下。
FKTTSManager(百度语音合成版)下载