1. TTS 能力简介
语音合成技术(Text To Speech),简称 TTS,是一种把文字智能地转化为自然语音流的技术。通过采用神经网络算法,TTS 文本输出的语音音律流畅,使得听者在听取信息时感觉自然,毫无机器语音输出的冷漠与生涩感。TTS 通常应用在电子图书、汽车电子、智能仪器等领域。
灵云 TTS SDK 具备支持多语种、多音色、多接口、多支持等产品优势。在新的女娲合成引擎的作用下,更是有了带情感的合成能力。灵云 TTS SDK 已经成功应用在百度翻译、导航犬(navidog)、天行听书、快的打车等产品上。
本文档旨在讲解如何快速地集成灵云 TTS 功能到开发者应用中。关于各服务接口更详细的说明,请参考灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。在阅读本文档之前,用户应该具备以下知识:
- 音频文件(pcm文件)的相关知识,如采样率等。
- 语音合成标记语言(SSML)的格式
- 应用开发的基本知识
1.1 概念解释
名称 | 说明 |
---|---|
Session | Session用来标记一个能力运行过程的上下文。一个应用最多可同时创建的Session数会受到授权的限制 |
云端合成 | 由云端服务器提供合成结果的方式。使用云端能力需要加上hci_tts_cloud_synth模块 |
本地合成 | 通过本地运算来得到合成结果的方式。使用本地能力需要加上hci_tts_local_synth模块和音库文件。目前提供v8,v9两种本地合成方式,v8是传统音色,v9是带情感的音色。 |
1.2 能力定义(capkey)
- 云端中文能力
capkey | 音色 |
---|---|
tts.cloud.wangjing | 女声 |
tts.cloud.wangjing.v9 | 带情感的女声 |
tts.cloud.haobo | 男声 |
tts.cloud.xixi | 女童声 |
tts.cloud.xiaokun | 女声 |
- 本地 TTS 能力
capkey | 说明 | 所需本地资源文件 |
---|---|---|
tts.local.synth | 本地tts | CNPackage.dat,中文音库文件,必选 ENPackage.dat,英文音库文件,可选 DMPackage.dat,用户个性定制库,包括用户词表和用户录音 |
tts.local.synth.v9 | 本地带情感tts | CNPackage.dat,中文音库文件,必选 ENPackage.dat,英文音库文件,可选 DMPackage.dat,用户个性定制库,包括用户词表和用户录音 |
在TTS能力中,本地资源文件就是音库文件,可参考3.2.2 本地能力语音合成。
- 外文 TTS 能力 常用外文能力如下:
能力key | 音色 | 语种 |
---|---|---|
tts.cloud.serena | 女声 | 英语 |
tts.cloud.daniel | 男声 | 英语 |
tts.cloud.thomas | 男声 | 法语 |
tts.cloud.sebastien | 男声 | 法语 |
tts.cloud.kyoko | 女声 | 日语 |
tts.cloud.narae | 女声 | 韩语 |
1.3 使用流程
2. TTS 能力使用说明
2.1 准备工作
下载语音合成SDK并解压缩。
如果需要使用本地语音合成,请下载相应资源包并解压缩。
2.2 使用 iOS 版 SDK
必选模块
- libcurl_device_simulator_iOS7.1.a
- libhci_sys_device_simulator_iOS7.1.a
- libhci_tts_device_simulator_iOS7.1.a
云端合成
- libhci_tts_cloud_synth_device_simulator_iOS7.1.a
- libjtspeex_device_simulator_iOS7.1.a
- libjtopus_device_simulator_iOS7.1.a
本地合成
- libhci_tts_local_synth_device_simulator_iOS7.1.a
- libhci_tts_local_synth_v9_device_simulator_iOS7.1.a
2.3 静态库导入
在SDK解压目录下的libs文件夹中包含HWR能力所需要的静态库,开发者可以根据需要进行选择。
请在工程目录结构中,添加手写识别(HWR)SDK,在选项TARGETS--> Build Phases-->Link Binary With Libraries-->Add Other,选择相应静态库文件并确认。
- 添加系统依赖框架(framework)TARGETS-->Build Phases-->Link Binary With Libraries--> + -->UIKit.fframework,Foundation.framework,SystemConfiguration.framework,Accelerate.framework,CoreLocation.framework
具体请参考TTS示例工程。
- 添加系统依赖框架(framework)TARGETS-->Build Phases-->Link Binary With Libraries--> + -->UIKit.fframework,Foundation.framework,SystemConfiguration.framework,Accelerate.framework,CoreLocation.framework
将语音合成(TTS)SDK的头文件导入您的工程中
- hci_sys.h
- hci_tts.h
最后语音合成(TTS)SDK的编译环境是 libc++,在选项TARGETS--> Build Settings-->C++ Standard Library,选择libc++,另外设置Other Link Flag为-ObjC。
3. TTS 能力集成说明
3.1 灵云授权认证
3.1.1 初始化灵云 SDK 通用模块
在调用ASR能力之前,需要初始化灵云SDK的通用模块。详见灵云SDK开发手册
iOS示例代码
HCI_ERR_CODE errCode = HCI_ERR_NONE;
// appkey, developerKey, cloudUrl, authPath为必填项。
// 其他可配置信息请查询灵云SDK开发手册hci_init函数说明。
NSString *appkey = @""; //开发者社区申请所得
NSString *developerKey = @""; //开发者社区申请所得
NSString *cloudUrl = @""; //开发者社区申请所得
NSString *authPath = @""; //授权文件所在路径,一般设置为沙盒Document路径
NSString *config = [NSString stringWithFormat:@"appkey=%@,
developerKey=%@,
cloudUrl=%@,
authPath=%@",
appkey,
developerKey,
cloudUrl,
authPath];
errCode = hci_init(config.UTF8String);
if (errCode != HCI_ERR_NONE && errCode != HCI_ERR_SYS_ALREADY_INIT) {
NSLog(@"hci_init failed, error: %d", errCode);
} else {
NSLog(@"hci_init success");
}
3.1.2 授权检测
在初始化灵云SDK的通用模块后,还需要调用授权检测函数获取云端授权。
- iOS代码
//获取过期时间 int64 expireTime; int64 currentTime = (int64)time(NULL); HCI_ERR_CODE errCode = hci_get_auth_expire_time(&expireTime); if (errCode == HCI_ERR_NONE) { if (expireTime < currentTime) { errCode = hci_check_auth(); if(errCode == HCI_ERR_NONE){ NSLog(@"check auth success"); return YES; }else{ NSLog(@"check auth failed, error: %@", errCode); return NO; } }else{ //没有过期 NSLog(@"auth can use continue"); return YES; } } //读取授权文件出现错误 else if(errCode == HCI_ERR_SYS_AUTHFILE_INVALID){ errCode = hci_check_auth(); if(errCode == HCI_ERR_NONE){ NSLog(@"check auth success"); return YES; }else{ NSLog(@"check auth failed, error: %@", errCode); return NO; } }else{ NSLog(@"check auth failed, error: %@", errCode); return NO; }
3.2 TTS语音合成
3.2.1 云端能力语音合成
3.2.1.1 TTS 能力初始化
云端能力的capkey都是以tts.cloud
开头。云端能力可以选择多个不同的播音员和语种,详见灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛。
- iOS代码
// initCapKeys为必填项,能力初始化时可以设置多个capkey,以分号间隔。 // 其他可配置信息请查询开发手册hci_tts_init函数说明。 NSString *initCapKeys = @"tts.cloud.xixi;tts.cloud.xiaokun"; //可以包含多种能力,用';'分号隔开 NSString *config = [NSString stringWithFormat:@"initCapKeys =%@", initCapKeys]; HCI_ERR_CODE errCode = HCI_ERR_NONE; errCode = hci_tts_init(config.UTF8String); if (errCode != HCI_ERR_NONE){ NSLog(@"hci_tts_init failed, error:%d", errCode); return NO; } NSLog(@"hci_tts_init success"); return YES;
3.2.1.2 创建TTS Session
- iOS代码
//开启session HCI_ERR_CODE errCode = HCI_ERR_NONE; NSString *config = @"capKey=tts.local.synth"; int sessionID; //开启会话成功后,会返回的会话ID errCode = hci_tts_session_start(config.UTF8String, &sessionID); if (errCode != HCI_ERR_NONE) { NSLog(@"hci_tts_session_start failed, error:%d", errCode); return NO; } NSLog(@"hci_tts_session_start success"); return YES;
3.2.1.3 TTS 合成
iOS代码
void *SELF = (__bridge void *)self; err_code = hci_tts_synth( session_id, (char*)txt, NULL, TtsSynthCallbackFunction, SELF );
合成函数的第三个参数用来设置合成效果,不用时可以为空。和前面一样,设置参数以“字段=值”形式的字符串的方式给出。用户可以设置合成音量、语速、标点符号读法、数字读法等。
第四个参数是接收合成结果的回调函数。当有合成结果时,SDK会触发回调函数,并把合成结果以TTS_SYNTH_RESULT对象的形式传递给用户。第五个参数将作为pvUserParam参数传递给回调函数。合成结果对象的定义如下:
iOS回调
bool HCIAPI TtsSynthCallbackFunction(_OPT_ _IN_ void * pvUserParam, _MUST_ _IN_ TTS_SYNTH_RESULT * psTtsSynthResult, _MUST_ _IN_ HCI_ERR_CODE hciErrCode) { if(hciErrCode != HCI_ERR_NONE){ return false; } SynthViewController *synthVC = (__bridge SynthViewController *)pvUserParam; if (psTtsSynthResult->pvVoiceData != NULL) { // 将合成的音频写入文件 NSData *voiceData = [NSData dataWithBytes:psTtsSynthResult->pvVoiceData length:psTtsSynthResult->uiVoiceSize]; [synthVC writeToFileWithString:voiceData withFileName:@"synthResult.pcm"]; NSLog(@"callback voice size : %d",psTtsSynthResult->uiVoiceSize); } //mark 回调结果 if (psTtsSynthResult->nMarkCount > 0) { //s3ml的配置结果 for (int i=0; i<psTtsSynthResult->nMarkCount; ++i) { NSLog(@"MarkName: %s,with the time in audio:%d",psTtsSynthResult->pMark[i].pszName,psTtsSynthResult->pMark[i].time); } } // 此回调函数返回false会中止合成,返回true表示继续合成 return true; }
合成普通文本
以合成“8月27日,在第十三届全国运动会即将开幕之际,中共中央总书记、国家主席、中央军委主席习近平在天津会见全国群众体育先进单位、先进个人代表和全国体育系统先进集体、先进工作者代表以及在本届全运会群众比赛项目中获奖的运动员代表,并发表重要讲话。”这样一段文本为例,合成过程如下:
SDK按照TtsSynthResult对象中对应的文字提供音频数据。
3.2.1.4 释放 Session
- iOS代码
hci_tts_session_stop(session);
3.2.2 本地能力语音合成
和云端能力不同,本地TTS能力必须提供本地音库资源文件才能工作。因此有两个重要参数:dataPath
与resPrefix
。dataPath
参数在TTS能力初始化时,指定本地资源的根目录;resPrefix
参数可进一步指定使用哪一种具体音色。
3.2.2.1 TTS 能力初始化
本地能力的 capkey 只有 tts.local.synth 和 tts.local.synth.v9 两种,用户通过提供不同的音库文件来选择生成不同的音频效果。这两种能力的使用方式均一致,不同的地方在于使用不同的库,参见2. TTS 能力使用说明中对库文件的介绍。在调用初始化方法之前,确保本地资源已拷贝到dataPath
目录下。
示例代码如下:
- iOS代码
//initCapKeys为必填项,能力初始化时可以设置多个capkey,以分号间隔。其他可配置信息请查询开发手册hci_tts_init函数说明。 NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil]; //本地能力所需本地资源所在路径 NSString *initCapKeys = @"tts.local.synth"; //可以包含多种能力,用';'分号隔开 NSString *config = [NSString stringWithFormat:@"dataPath =%@, initCapKeys =%@", dataPath, initCapKeys]; HCI_ERR_CODE errCode = HCI_ERR_NONE; errCode = hci_tts_init(config.UTF8String); if (errCode != HCI_ERR_NONE){ NSLog(@"hci_tts_init failed, error:%d", errCode); return NO; } NSLog(@"hci_tts_init success"); return YES;
3.2.2.2 创建 TTS Session
iOS 代码
//开启session HCI_ERR_CODE errCode = HCI_ERR_NONE; NSString *config = @"capKey=tts.local.synth"; int sessionID; //开启会话成功后,会返回的会话ID errCode = hci_tts_session_start(config.UTF8String, &sessionID); if (errCode != HCI_ERR_NONE){ NSLog(@"hci_tts_session_start failed, error:%d", errCode); return NO; } NSLog(@"hci_tts_session_start success"); return YES;
当在一个应用中使用多种音库时,可通过TtsConfig.SessionConfig.PARAM_KEY_RES_PREFIX配置项便文件前缀来区分不同音库。例如,当前有Barron音库与XiaoKun_Common音库,这两个音库下的资源名称都是一样的,可通过以下两种方式配置不同的session,合成不同音色的声音。
- 将Barron和XiaoKunCommon音库的文件分别手动加上"Barron”和"XiaoKunCommon"前缀, 放置在datapath路径下, Session A 使用 "resPrefix=Barron", Session B使用 "resPrefix=XiaoKun_Common";
- 将Barron和XiaoKun_Common音库的文件分别放在Barron文件夹与XiaoKun_Common文件夹下,将这两个文件夹放置在datapath路径下,Session A 使用 "resPrefix=Barron/", Session B使用 "resPrefix=XiaoKun_Common/" ;
3.2.2.3 TTS 合成
和3.2.1.3节相同
3.2.2.4 释放 Session
和3.2.1.4节相同
3.3 灵云系统反初始化
- iOS代码
hci_tts_release(); hci_release();
4. 常用配置说明
- 数字读法 配置数字的读法,例如“1200”是读成“一千二百”还是“一二零零”。通过digitMode配置
- 姓氏多音字 配置例如“单、仇”这样的字在作为姓氏时的特殊读法,通过namePolyphone配置(仅本地)
- 1、2的特殊读法 是读成“一”、“二”还是读成“幺”、“两”,通过specialOne和specialTwo配置(仅本地)
- 背景音配置 通过backaudiopath配置(仅本地)
- 输出音频格式 通过 audioFormat 配置
5. FAQ
Q: 你们的tts,中文是否支持方言播报,如播报湖南话、四川话等。
A: SDK8.1暂不支持方言播报。
Q: 我用的是官网下载的xiaokun音库,我发现她播报英文的时候,是一个字一个字去播放的。试过了engMode=auto,english两个参数,依然如此。
A: Xiaokun音库适合播放中文,不适合播放英文。Xiaokun音库里自带的英文资源EnPackage.dat读英文就是这个效果。如果希望体验纯正的美式英语,建议下载一个原生英语音库(如Cameal),再将Cameal音库下的EnPackage.dat文件替换您的工程中的Xiaokun音库的同名文件。Cameal音库读英文,效果就自然多了。
Q:我运行你们的tts_example,发现合成结果保存到了一个synth.pcm中,我要怎么才能播放这个文件?你们是否支持实时播放的方式?
A: tts如果您不使用播放器,直接调用tts_synth接口,结果是保存到一个文件,默认是16k16bit pcm。这个文件无法使用windows media player打开,可以用cooledit打开此文件。我们的tts支持实时播放的方式,如有需要可以使用我们的TTSPlayer。
Q: 我看你们tts本地播放的capkey是tts.local.synth,这个和音库有关系吗?xiaokun,wangjing,xixi等音库,都可以用这个capkey吗?
A: tts本地能力的capkey都是tts.local.synth,云端能力才指定发音人,如tts.cloud.wangjing,tts.cloud.xixi,本地能力,最终用什么音库发声,取决于代码datapath指定路径下,组入的是什么音库的资源文件。比如,组入的是wangjing的本地资源,那么发声人就是wangjing。
Q: 你们的tts,我调到最大声,发现声音还是有些小,在我们的车机上使用,大概低了6db左右。这个还有办法增加吗?
A: 首先确认ttsconfig的volume参数值已调到最大值9.99,音量仍不足的情况下,尝试调整gainfactor增益参数(取值范围:【2,8】),可以继续增大音量。但是gainfactor参数调节太大,可能会造成破音。详见开发手册。
Q: 你们的tts,都支持合成为哪些格式的音频文件?
A: 支持合成为pcm8k16bit,pcm16k16bit,alaw8k8bit,ulaw8k8bit等音频格式,云端支持为MP3格式,详见开发手册。文件可以保存为.wav结尾,但是并不是windows wav,使用wma无法直接打开。建议使用cooledit等音频编解码工具进行播放。
Q: 我看你们的tts能力,本地的capkey除了tts.local.synth,还有一个tts.local.synth.sing,这个具体是什么区别?
A: tts.local.synth 是普通的tts本地合成对应的 capkey,tts.local.synth.sing 则是本地歌唱能力,需要有对应的通过S3ML标记语言书写的歌谱。目前SDK8.1暂不支持本地歌唱能力。