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模块和音库文件 |
1.2 能力定义(capkey)
云端中文能力 |capkey|音色| |-------|----|----------| |tts.cloud.wangjing|女声| |tts.cloud.haobo |男声| |tts.cloud.xixi|女童声| |tts.cloud.xiaokun|女声
本地 TTS 能力 |capkey|所需本地资源文件| |-------|-------------------| |tts.local.synth|CNPackage.dat,中文音库文件,必选
ENPackage.dat,英文音库文件,可选
DMPackage.dat,用户个性定制库,包括用户词表和用户录音
Default.conf,合成参数配置文件,必选 | |tts.local.synth.sing|CNPackage.dat,中文音库,必选
DMPackage.dat,用户个性定制库,可选
Default.conf,合成参数配置文件,必选|在TTS能力中,本地资源文件就是音库文件,可参考3.2.2 本地能力语音合成。
外文 TTS 能力 常用外文能力如下: |能力key|音色|语种| |--------|-----|----| |tts.cloud.serena|女声|英语 | |tts.cloud.daniel|男声|英语 | |tts.cloud.thomas|男声|法语 | |tts.cloud.sebastien|男声|法语| |tts.cloud.kyoko|女声|日语 | |tts.cloud.narae|女声| 韩语|
其他请参考灵云SDK开发手册
1.3 使用流程
2. TTS 能力使用说明
2.1 准备工作
下载语音合成SDK并解压缩。
如果需要使用本地语音合成,请下载相应资源包并解压缩。
2.2 使用 Android 版 SDK
Android 版的 SDK 提供如下文件:
文件或目录 | 说明 |
---|---|
armeabi、armeabi-v7a、x86等 | 存放灵云能力所需so文件的目录,依照不同的处理器架构分类 |
hcicloud-5.0.jar | 提供灵云能力接口的jar包 |
使用时将这些文件复制到安卓工程的libs目录下,并把jar包添加到工程中。
2.2.1 库文件介绍
必选模块
- libcurl.so
- libhci_sys.so
- libhci_sys_jni.so
- libhci_tts.so
- libhci_tts_jni.so
- libstlport_shared.so
云端合成
- libhci_tts_cloud_synth.so
- libjtspeex.so
- libjtopus.so
本地合成
- libhci_tts_local_synth.so
2.2.2 添加用户权限
在工程 AndroidManifest.xml 文件中添加如下权限。
<!—通常需要设置一些sd卡路径(例如日志路径)为可写,因此需要能够写外部存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!—以下访问网络的权限均需要打开-->
<!--连接网络权限,用于执行云端能力 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
2.3 使用 C++ 版 SDK
C++ 版的 SDK 提供三个目录:include、lib 和 bin,include 目录存放头文件,lib 目录存放链接时需要输入的库文件,bin 目录存放运行时需要的动态库文件。使用 TTS SDK 需要使用的文件如下:
灵云 SDK 头文件
- hci_tts.h
- hci_sys.h
灵云 SDK 库文件
- hci_tts.lib
- hci_sys.lib
必选模块
- libhci_curl.dll
- hci_sys.dll
- hci_tts.dll
云端能力
- hci_tts_cloud_synth.dll
- jtspeex.dll 或者 jtopus.dll (根据所使用的编解码格式进行选择)
本地 TTS 能力
- hci_tts_local_synth.dll
歌唱 TTS 能力
- hci_tts_local_synth_sing.dll
2.4 使用 iOS 版 SDK
必选模块
- libcurl_device_simulator_iOS5.1.1.a
- libhci_sys_device_simulator_iOS5.1.1.a
- libhci_tts_device_simulator_iOS5.1.1.a
云端合成
- libhci_tts_cloud_synth_device_simulator_iOS5.1.1.a
- libjtspeex_device_simulator_iOS5.1.1.a
- libjtopus_device_simulator_iOS5.1.1.a
本地合成
- libhci_tts_local_synth_device_simulator_iOS5.1.1.a
适配器选择(只选其一)
- libhci_tts_only_cloud_adapter_device_simulator_iOS5.1.1.a(只使用云端能力)
- libhci_tts_only_local_adapter_device_simulator_iOS5.1.1.a(只使用本地能力)
- libhci_tts_cloud_local_adapter_device_simulator_iOS5.1.1.a(既使用云端能力,又使用本地能力)
3. TTS 能力集成说明
3.1 灵云授权认证
3.1.1 初始化灵云 SDK 通用模块
调用通用模块初始函数来初始化灵云通用模块,例如:
Android代码
HciCloudSys.hciInit( "developerKey=01234567890, appKey=1234abcd,cloudUrl=api.hcicloud.com:8888, authPath=/storage/emulated/0/myApp/auth, logFileSize=500,logLevel=5, logFilePath=/storage/emulated/0/myApp/log,logFileCount=10", context);
C++代码
char * pszConfig = "developerKey=01234567890,appKey=1234abcd, \ cloudUrl=http://api.hcicloud.com:8888, \ authPath=document, \ logFileSize=500,logLevel=5, \ logFilePath=document/log/,logFileCount=10"; hci_init(pszConfig);
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"); }
所有配置以字符串的形式传入,按照“字段=值”的方式来组织。详细说明请参考灵云SDK开发手册。
针对Java代码,灵云 SDK 还提供了 InitParam 类来简化配置字符串的编写工作。
import com.sinovoice.hcicloudsdk.common.InitParam; // ............. InitParam initparam = new InitParam(); initparam.addParam(InitParam.AuthParam.PARAM_KEY_AUTH_PATH, "/storage/emulated/0/myApp/auth"); initparam.addParam(InitParam.AuthParam.PARAM_KEY_CLOUD_URL, "/api.hcicloud.com:8888"); // .............. String strConfig = initParam.getStringConfig(); int errCode = HciCloudSys.hciInit(strConfig, this); if (errCode != HciErrorCode.HCI_ERR_NONE && errCode != HciErrorCode.HCI_ERR_SYS_ALREADY_INIT) { mLogView.append("\nhciInit error: " + HciCloudSys.hciGetErrorInfo(errCode)); return; } else { mLogView.append("\nhciInit success"); }
3.1.2 授权检测
检查相应能力的授权是否有效。SDK提供了 HciCloudSys.hciCheckAuth
和 HciCloudSys.hciGetAuthExpireTime
两个函数,分别来检查授权合法性和授权截止时间。
细节请请参考灵云SDK模块通用开发指南。
3.2 TTS语音合成
3.2.1 云端能力语音合成
3.2.1.1 TTS 能力初始化
云端能力的capkey都是以tts.cloud
开头。云端能力可以选择多个不同的播音员和语种,详见灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛。
Android代码
Java和Android平台使用HciCloudTts.hciTtsInit来初始化TTS能力
TtsInitParam ttsInitParam = new TtsInitParam();
// 能力初始化时可以设置多个capkey,以分号间隔。
ttsInitParam.addParam(TtsInitParam.PARAM_KEY_INIT_CAP_KEYS, "tts.cloud.xixi;tts.cloud.xiaokun");
// ................
int errCode = HciCloudTts.hciTtsInit(ttsInitParam.getStringConfig());
if (errCode != HciErrorCode.HCI_ERR_NONE) {
ShowMessage("hciTtsInit error:" + HciCloudSys.hciGetErrorInfo(errCode));
return;
} else {
ShowMessage("hciTtsInit Success");
}
C++代码
string tts_init_config = "dataPath=./data,"; // 能力初始化时可以设置多个capkey,以分号间隔。 tts_init_config += ",initCapkeys=tts.cloud.xixi;tts.cloud.xiaokun"; err_code = hci_tts_init(tts_init_config.c_str()); if (err_code != HCI_ERR_NONE) { printf("hci_tts_init return (%d:%s) \n",err_code,hci_get_error_info(err_code)); return; }
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
Android代码
TtsConfig sessionConfig = new TtsConfig(); // 此capkey必须在HciCloudTts.hciTtsInit时已经初始化的范围内 sessionConfig.addParam(TtsConfig.SessionConfig.PARAM_KEY_CAP_KEY, "tts.cloud.xixi"); Session session = new Session(); int errCode = HciCloudTts.hciTtsSessionStart(sessionConfig.getStringConfig(), session); if (HciErrorCode.HCI_ERR_NONE != errCode) { ShowMessage("hciTtsSessionStart error:" + HciCloudSys.hciGetErrorInfo(errCode)); return; }
C++代码
int session_id = -1; HCI_ERR_CODE err_code = HCI_ERR_NONE; err_code = hci_tts_session_start( session_config.c_str(), &session_id ); if( err_code != HCI_ERR_NONE ) { return; }
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 合成
Android代码
通过HciCloudTts.hciTtsSynth和HciCloudTts.hciTtsSynthEx来分别合成string和byte[]类型的文字。
int errCode = HciCloudTts.hciTtsSynthEx(session, synthData, "", mTtsSynthCallback); if (errCode == HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciTtsSynth Success"); }else{ ShowMessage("hciTtsSynth error:" + HciCloudSys.hciGetErrorInfo(errCode)); }
C++代码
err_code = hci_tts_synth( session_id, (char*)txt, NULL, TtsSynthCallbackFunction, fp );
iOS代码
void *SELF = (__bridge void *)self; err_code = hci_tts_synth( session_id, (char*)txt, NULL, TtsSynthCallbackFunction, SELF );
合成函数的第三个参数用来设置合成效果,不用时可以为空。和前面一样,设置参数以“字段=值”形式的字符串的方式给出。用户可以设置合成音量、语速、标点符号读法、数字读法等,详见灵云SDK开发手册。
第四个参数是接收合成结果的回调函数。当有合成结果时,SDK会触发回调函数,并把合成结果以TtsSynthResult(java)或TTS_SYNTH_RESULT(C++)对象的形式传递给用户。第五个参数(仅C++)将作为pvUserParam参数传递给回调函数。合成结果对象的C++定义如下:
typedef struct _tag_TTS_SYNTH_RESULT
{
/// 数据缓冲区指针,数据格式由合成时候的配置决定
void * pvVoiceData;
/// 数据缓冲区长度,以字节为单位
unsigned int uiVoiceSize;
/// 本段数据对应的文本内容的起始指针
char * pszText;
/// 本段数据对应的文本长度,字节为单位
unsigned int uiTextLen;
/// 是否还有数据等待合成
bool bMore;
/// mark 标记
TTS_SYNTH_MARK *pMark;
/// mark数量。
unsigned int nMarkCount;
} TTS_SYNTH_RESULT;
Java代码的定义基本相同。
灵云 SDK 会把需要合成的文本按照语句逻辑关系分割成子句,再合成音频数据。SDK在子句划分和语音合成时都会触发回调函数,顺序通常是这样的:
1. 通知要合成的句子文本
此时传给回调的合成结果中,语音数据的内容为空,mCurrentSynthText(java)或pszText(C++)指向正在合成的文本,之后
2. 返回音频数据
SDK多次调用回调函数,合成对象的mVoiceData(java)或pvVoiceData(C++)指向合成后的音频数据,mCurrentSynthText或pszText内容为空
3. 开始下一句
再次返回要合成的文本,随后是数据。周而复始,直到所有文本合成结束
- Android代码
private static ITtsSynthCallback mTtsSynthCallback = new ITtsSynthCallback() {
@Override
public boolean onSynthFinish(int errorCode, TtsSynthResult result) {
// errorCode 为当前合成操作返回的错误码,如果返回值为HciErrorCode.HCI_ERR_NONE则表示合成成功
if (errorCode != HciErrorCode.HCI_ERR_NONE) {
Log.e(TAG, "synth error, code = " + errorCode);
return false;
}
// result记录本次合成的数据,result.getVoiceData()返回合成数据的二进制数据
if(result != null && result.getVoiceData() != null){
int length = result.getVoiceData().length;
if (length > 0) {
// 记录、处理合成数据 ...
}
}
// result.getTtsSynthMark()返回S3ML标记的名称和时间点
if(result.getTtsSynthMark().size() > 0)
{
for(int i=0;i<result.getTtsSynthMark().size();++i)
{
// 处理mark信息
}
}
}
C++代码
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; } //printf("voice data size %d\n",psTtsSynthResult->uiVoiceSize); // 将合成结果写入文件 if (psTtsSynthResult->pvVoiceData != NULL) { FILE * fp = (FILE *)pvUserParam; fwrite(psTtsSynthResult->pvVoiceData, psTtsSynthResult->uiVoiceSize, 1, fp); } }
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对象中对应的文字提供音频数据。
合成s3ml文本 合成文本如下:
<?xml version="1.0" encoding="GB18030"?>
<speak version="1.0" xml:lang="zh-cn">
从这里<mark name="here"/>开始出发,到那里<mark name="there"/>停止。
</speak>
此时返回结果中会有mark节点信息,见下图
注: 要合成s3ml文本,必须设置 tagmode 参数。示例代码如下:
Android代码
TtsConfig synthConfig = new TtsConfig(); synthConfig.addParam(TtsConfig.BasicConfig.PARAM_KEY_TAG_MODE, "s3ml"); HciCloudTts.hciTtsSynthEx(session, synthData, synthConfig.getStringConfig(), mTtsSynthCallback);
C++代码
hci_tts_synth( session_id, (char*)txt, "tagmode=s3ml", TtsSynthCallbackFunction, fp );
iOS代码
void *SELF = (__bridge void *)self; hci_tts_synth( session_id, (char*)txt, "tagmode=s3ml", TtsSynthCallbackFunction, SELF );
3.2.1.4 释放 Session
Android代码
HciCloudTts.hciTtsSessionStop(session);
C++代码
hci_tts_session_stop(session);
iOS代码
hci_tts_session_stop(session);
3.2.2 本地能力语音合成
和云端能力不同,本地TTS能力必须提供本地音库资源文件才能工作。
3.2.2.1 TTS 能力初始化
本地能力的 capkey 只有 tts.local.synth 和 tts.local.synth.sing 两种,用户通过提供不同的音库文件来选择生成不同的音频效果。音库文件的明细请参考灵云开发手册。
示例代码如下:
Android代码
TtsInitParam ttsInitParam = new TtsInitParam(); ttsInitParam.addParam(TtsInitParam.PARAM_KEY_DATA_PATH, "/storage/......"); //存放本地资源文件的路径,使用本地资源时必须提供此配置 ttsInitParam.addParam(TtsInitParam.PARAM_KEY_INIT_CAP_KEYS, "tts.local.synth"); ................ int errCode = HciCloudTts.hciTtsInit(ttsInitParam.getStringConfig()); f (errCode != HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciTtsInit error:" + HciCloudSys.hciGetErrorInfo(errCode)); return; } else { ShowMessage("hciTtsInit Success"); }
C++代码
string tts_init_config = "dataPath=./data"; tts_init_config += ",initCapkeys=tts.local.synth"; HCI_ERR_CODE err_code = hci_tts_init(tts_init_config.c_str());
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;
本地资源文件的说明请参考灵云SDK开发手册。
3.2.2.2 创建 TTS Session
Android代码
TtsConfig sessionConfig = new TtsConfig(); sessionConfig.addParam(TtsConfig.SessionConfig.PARAM_KEY_CAP_KEY, “tts.local.synth”); // 此capkey必须在HciCloudTts.hciTtsInit时已经初始化的范围内 sessionConfig.addParam(TtsConfig.SessionConfig.PARAM_KEY_RES_PREFIX, “Barron_”); // 设置资源文件名称前缀 Session session = new Session(); int errCode = HciCloudTts.hciTtsSessionStart(sessionConfig.getStringConfig(), session); if (HciErrorCode.HCI_ERR_NONE != errCode) { ShowMessage("hciTtsSessionStart error:" + HciCloudSys.hciGetErrorInfo(errCode)); return; }
C++代码
HCI_ERR_CODE err_code = HCI_ERR_NONE; string session_config = "capkey=tts.local.synth"; session_config += ",resPrefix=Barron_"; int session_id = -1; err_code = hci_tts_session_start( session_config.c_str(), &session_id ); if( err_code != HCI_ERR_NONE ) { return; }
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.PARAMKEY_RES_PREFIX配置项便是设置文件前缀。例如要使用Barron和XiaoKun_Common两种音库,就要创建两个session,分别设置资源文件前缀为“Barron”和"XiaoKunCommon"。在放置音库文件时,需要将Barron和XiaoKunCommon音库的文件分别手动加上"Barron”和"XiaoKunCommon"前缀,以此来避免文件名字冲突。
3.2.2.3 TTS 合成
和3.2.1.3节相同
3.2.2.4 释放 Session
和3.2.1.4节相同
3.3 灵云系统反初始化
Android代码
HciCloudTts.hciTtsRelease(); HciCloudSys.hciRelease();
C++代码
hci_tts_release(); hci_release();
iOS代码
hci_tts_release(); hci_release();
4. 常用配置说明
- 数字读法 配置数字的读法,例如“1200”是读成“一千二百”还是“一二零零”。通过digitMode配置
- 姓氏多音字 配置例如“单、仇”这样的字在作为姓氏时的特殊读法,通过namePolyphone配置(仅本地)
- 1、2的特殊读法 是读成“一”、“二”还是读成“幺”、“两”,通过specialOne和specialTwo配置(仅本地)
- 背景音配置 通过backaudiopath配置(仅本地)
- 输出音频格式 通过 audioFormat 配置 其他请参考灵云SDK开发手册。
5. FAQ
Q: 你们的tts,中文是否支持方言播报,如播报湖南话、四川话等。
A: 方言仅支持粤语,shuyi 音库。其他方言语种,不支持。
Q: 我用的是官网下载的xiaokun音库,我发现她播报英文的时候,是一个字一个字去播放的。试过了engMode=auto,english两个参数,依然如此。
A: Xiaokun音库适合播放中文,不适合播放英文。Xiaokun音库里自带的英文资源EnPackage.dat读英文就是这个效果。如果希望体验纯正的美式英语,建议下载一个原生英语音库(如Cameal),再将Cameal音库下的EnPackage.dat文件替换您的工程中的Xiaokun音库的同名文件。Cameal音库读英文,效果就自然多了。
Q:我用你们的ttsplayerexample进行测试,capkey=tts.cloud.wangjing,服务器返回11号错误:service response failed。我除了填入账号信息,什么配置都没有修改,这个可能是什么原因?
A: 经检查,您将我们示例程序中的tts.txt这个文件的文本格式修改为了GBK,默认应为UTF8。我们的TTS输入的合成文本格式必须是UTF8。
Q:我运行你们的tts_example,发现合成结果保存到了一个synth.pcm中,我要怎么才能播放这个文件?你们是否支持实时播放的方式?
A: tts如果您不使用播放器,直接调用tts_synth接口,结果是保存到一个文件,默认是16k16bit pcm。这个文件无法使用windows media player打开,可以用cooledit打开此文件。我们的tts支持实时播放的方式,播放器相关的代码封装在hcicloud_player-5.0.jar中。您运行我们的ttsplayerexample示例程序,可以体验。
Q: 你们的ttsplayer,是否支持自定义输出的音频流类型?我看你们的示例程序,默认是在扬声器里输出。如果我希望在听筒、蓝牙音轨中进行输出,应该如何操作?
A: 支持,hcicloud_player-5.0.jar中,封装了对应的方法。播放器播放,mTtsPlayer.play(text,ttsConfig.getStringConfig(),mStreamtype),其中第三个参数即为音频流类型,这个参数值在车机项目上等,常常存在自定义的情况。我们的mStreamtype传入的是int型,各参数对应值默认如下,比如听筒输出的streamtype=0。
Q: 我如何可以得知播放器的状态和当前是否可以停止播放?你们的状态回调和错误回调,都是走的同一个回调函数吗?
A: 通过hci_tts_player_get_state ( )接口获取播放器状态,通过tts_player_can_stop ( ) 接口查询是否当前是否可以停止播放器。 我们的播放器,有事件回调、进度回调、错误回调等,都是分别在不同的结构体里定义的。比如事件回调是Callback_PlayerEventStateChange,进度回调PlayerEventProgressChange,错误回调Callback_PlayerEventPlayerError。iOS系统还有一个专门的Callback_PlayerSetAudioSession。
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标记语言书写的歌谱。目前本地歌唱能力,暂时仅支持xixi音库。