# 概览

AIUI目前支持两种方式进行语音合成:

  1. 集成MSC库,调用SpeechSynthesizer接口进行语音合成;
  2. 调用AIUI接口,使用云端语音合成(云端TTS),云端下发音频流到客户端进行播放。此方式又分为主动语音合成语义后合成

主动语音合成与语义后合成的区别:

  • **主动语音合成:**即客户端发送文本给云端,云端返回合成音频给客户端。开发者通过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();
				}
			} breakdefault:
				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;
		}
	}
};