# 概览
AIUI目前支持两种方式进行语音合成:
主动语音合成与语义后合成的区别:
**主动语音合成:**即客户端发送文本给云端,云端返回合成音频给客户端。开发者通过AIUIAgent主动发送
CMD_TTS
消息给AIUI,云端会下发该文本对应的音频,客户端再进行播放;**语义后合成:**即与AIUI交互的过程中,云端会将语义结果中answer内容对应的合成音频下发到客户端。开发者只需要在云端设置中勾选合成音频下发功能,并设置好发音人,语言等参数,在交互过程中,云端会在得到语义结果后将tts合成音频下发到客户端,客户端能直接将结果进行播报,其中合成的音频内容为语义结果answer字段的text值。
如需使用第一种方式请参考MSC集成文档 (opens new window),本节着重介绍云端TTS,云端TTS可以省去集成MSC库的步骤,直接获取云端下发的音频即可。
# 主动语音合成
# 集成示例
开发者使用AIUIAgent发送CMD_TTS消息,arg1字段为具体操作,params字段为合成参数,data字段为待合成的文本数据(文本数据最大支持8192字节,超过部分字节不会被合成),示例:
String ttsStr = "我是要合成的文本"; //得到待合成文本
byte[] ttsData = ttsStr.getBytes("utf-8"); //转为二进制数据
StringBuffer params = new StringBuffer(); //构建合成参数
params.append("vcn=xiaoyan"); //合成发音人
params.append(",speed=50"); //合成速度
params.append(",pitch=50"); //合成音调
params.append(",volume=50"); //合成音量
//开始合成
AIUIMessage startTts = new AIUIMessage(AIUIConstant.CMD_TTS,AIUIConstant.START, 0, params.toString(), ttsData);
mAIUIAgent.sendMessage(startTts);
注:sdk默认会播放云端下发的TTS音频,若不需要sdk直接播报,则需要在配置文件中配置tts参数,将play_mode配置为user,具体请参考云端TTS音频播放,开发者在EVENT_RESULT
事件中可以获取到下发的音频数据,由开发者自己进行播报,具体请参考音频结果解析。
arg1取值说明:
类型 | 取值 | 含义 | 参数 |
START | 1 | 开始合成 | 合成发音人,语速语调等 |
CANCEL | 2 | 取消合成 | 无 |
PAUSE | 3 | 暂停播放 | 无 |
RESUME | 4 | 恢复播放 | 无 |
合成参数示例:
String params = "vcn=xiaoyan,speed=50,pitch=50,volume=50"
参数字段说明:
名称 | 含义 |
vcn | 发音人,如xiaoyan。支持发音人请参考发音人列表 |
speed | 语速,0-100 |
pitch | 语调,0-100 |
volume | 音量,0-100 |
ent | 引擎,默认aisound,如果需要较好的效果,可设置成xtts |
# 支持的发音人
发音人名称 | vcn取值 | 方言 |
嘉嘉 | jiajia | 普通话 |
小燕 | xiaoyan | 普通话 |
小宇 | xiaoyu | 普通话 |
小研 | vixy | 普通话 |
小琪 | vixq | 普通话 |
小莉 | vixl | 普通话 |
楠楠 | vinn | 普通话 |
老孙 | vils | 普通话 |
小新 | vixx | 普通话 |
小蓉 | vixr | 四川话 |
小梅 | vixm | 广东话 |
小芸 | vixyun | 东北话 |
小坤 | vixk | 河南话 |
小强 | vixqa | 湖南话 |
小莹 | vixying | 山西话 |
虫虫(ent参数需设置为xtts) | x_chongchong | 精品普通话 |
# 语义后合成
在平台配置勾选交互音频下发功能后,设置好发音人,语言等参数,云端在得到语义结果后即调tts得到音频下发到客户端,开发者只需要解析对应的事件即可获得该音频数据。
注:有正常语义结果才有合成音频下发,如nlp语义结果rc字段为4则无音频下发。
# 音频结果解析
SDK接收到云端下发的音频后,会通过EVENT_RESULT抛出合成音频和缓存进度,音频数据编码格式为pcm,解析音频数据请参考以下示例:
private AIUIListener mAIUIListener = new AIUIListener() {
@Override
public void onEvent(AIUIEvent event) {
case AIUIConstant.EVENT_RESULT: {
try {
JSONObject bizParamJson = new JSONObject(event.info);
JSONObject data = bizParamJson.getJSONArray("data").getJSONObject(0);
JSONObject params = data.getJSONObject("params");
JSONObject content = data.getJSONArray("content").getJSONObject(0);
String sub = params.optString("sub");
if ("tts".equals(sub)) {
if (content.has("cnt_id")) {
String sid = event.data.getString("sid");
String cnt_id = content.getString("cnt_id");
byte[] audio = event.data.getByteArray(cnt_id); //合成音频数据
/**
*
* 音频块位置状态信息,取值:
* - 0(合成音频开始块)
* - 1(合成音频中间块,可出现多次)
* - 2(合成音频结束块)
* - 3(合成音频独立块,在短合成文本时出现)
*
* 举例说明:
* 一个正常语音合成可能对应的块顺序如下:
* 0 1 1 1 ... 2
* 一个短的语音合成可能对应的块顺序如下:
* 3
**/
int dts = content.getInt("dts");
int frameId = content.getInt("frame_id");// 音频段id,取值:1,2,3,...
int percent = event.data.getInt("percent"); //合成进度
boolean isCancel = "1".equals(content.getString("cancel")); //合成过程中是否被取消
}
}
} catch (Throwable e) {
e.printStackTrace();
}
} break;
default:
break;
}
}
};
# 音频播放控制
在aiui.cfg中配置tts字段即可,示例如下:
{
"tts": {
"play_mode": "sdk", // 播放模式,取值:sdk(内部播放,默认),user(外部自行播放)
"buffer_time": "0", // 音频缓冲时长,当缓冲音频大于该值时才开始播放,默认值:0ms
"stream_type": "3", // 播放音频流类型,取值参考AudioManager类,默认值:3
"audio_focus": "0" // 播放音频时是否抢占焦点,取值:1, 0(默认值)
}
}
若play_mode
设置为sdk,则云端下发的音频,sdk会自动播放(暂只支持Android系统),若设置为user,则由开发者在EVENT_RESULT中解析sub为tts
的事件,具体解析请参考tts结果解析。
当使用sdk自动播放时,sdk会抛出EVENT_TTS事件反馈合成进度等信息,示例如下:
private AIUIListener mAIUIListener = new AIUIListener() {
@Override
public void onEvent(AIUIEvent event) {
case AIUIConstant.EVENT_TTS: {
switch (event.arg1) {
case AIUIConstant.TTS_SPEAK_BEGIN:
showTip("开始播放");
break;
case AIUIConstant.TTS_SPEAK_PROGRESS:
showTip("缓冲进度为" + mTtsBufferProgress +
", 播放进度为" + event.data.getInt("percent")); // 播放进度
break;
case AIUIConstant.TTS_SPEAK_PAUSED:
showTip("暂停播放");
break;
case AIUIConstant.TTS_SPEAK_RESUMED:
showTip("恢复播放");
break;
case AIUIConstant.TTS_SPEAK_COMPLETED:
showTip("播放完成");
break;
default:
break;
}
} break;
default:
break;
}
}
};