发音人
合成分类
主动合成
免费发音人:小娟、聆小樱、聆小璇(在AIUI应用配置页面,开启语音合成能力并选择对应发音人进行保存来激活)
主动合成集成示例:在线TTS
注:一次请求最多合成2000字
// 获取待合成文本
String ttsStr = "我是要合成的文本";
// 转为二进制数据
byte[] ttsData = ttsStr.getBytes("utf-8");
// 构建合成参数,一般包含发音人、语速、音调、音量
StringBuffer params = new StringBuffer();
// 发音人,发音人列表:https://aiui-doc.xf-yun.com/project-1/doc-93/
params.append("vcn=x2_xiaojuan");
// 语速,取值范围[0,100]
params.append(",speed=50");
// 音调,取值范围[0,100]
params.append(",pitch=50");
// 音量,取值范围[0,100]
params.append(",volume=50");
//开始合成
AIUIMessage startTTS = new AIUIMessage(AIUIConstant.CMD_TTS,AIUIConstant.START, 0, params.toString(), ttsData);
mAIUIAgent.sendMessage(startTTS);
//取消合成
AIUIMessage cancelTTS = new AIUIMessage(AIUIConstant.CMD_TTS,AIUIConstant.CANCEL, 0, params.toString(), ttsData);
mAIUIAgent.sendMessage(cancelTTS);
//暂停播放
AIUIMessage pauseTTS = new AIUIMessage(AIUIConstant.CMD_TTS,AIUIConstant.PAUSE, 0, params.toString(), ttsData);
mAIUIAgent.sendMessage(pauseTTS);
//恢复播放
AIUIMessage resumeTTS = new AIUIMessage(AIUIConstant.CMD_TTS,AIUIConstant.RESUME, 0, params.toString(), ttsData);
mAIUIAgent.sendMessage(resumeTTS);
主动合成集成示例:离线TTS
将合成发音人资源(联系商务)放到本地加载,修改aiui.cfg配置。合成接口与在线TTS一样。
资源说明
- xtts_common.jet,离线tts通用配置
- xtts_xiaoxue.jet,发音人xiaoxue的资源文件
发音人文件放到 assets 目录下,aiui.cfg配置相对路径。多个发音人用 ;
分割。
离线合成配置参考
aiui.cfg 配置:
"tts":{
// 使用xtts
"ent": "xtts",
// 离线引擎
"engine_type": "local",
// 资源类型
"res_type": "assets",
//配置发音人
"res_path": "xtts/xtts_common.jet;xtts/xtts_xiaoxue.jet"
},
离线发音人
联系讯飞确认
语义后合成
AIUI平台打开语音合成开启。异常情况不会合成音频,如nlp语义理解未命中(rc=4)。
可在应用配置中开启:
音频结果解析
SDK在EVENT_RESULT回调抛出合成音频和缓存进度,格式为16k 16bit 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); //合成音频数据
/**
*
* dts:音频块进度信息,取值:
* - 0(音频开始)
* - 1(音频中间块,可出现多次)
* - 2(音频结束)
* - 3(独立音频,合成短文本时出现)
*
* 举例说明:
* 常规合成dts顺序:
* 0 1 1 1 ... 2
* 短文本合成dts顺序:
* 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;
}
}
};
播放模式
1.SDK自动播放(默认)
2.使用第三方播放器
将aiui.cfg的play_mode配置为user(参考TTS音频播放),开发者在EVENT_RESULT
事件中获取音频后自己播放(参考音频结果解析)。
音频播放控制
aiui.cfg配置示例:
{
"tts": {
// 播放模式:sdk(sdk播放,默认,只支持安卓),user(开发者自己播放)
"play_mode": "sdk",
// 音频缓冲时长:缓冲音频大于buffer_time才播放,默认0ms
"buffer_time": "0",
// 音频类型,取值参考AudioManager类,默认值:3
"stream_type": "3",
// 播放是否抢占焦点:1(抢占), 0(不抢占,默认)
"audio_focus": "0"
}
}
播放状态回调
只支持Android,且播放模式为SDK:
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;
}
}
};
其他
部分技能返回播报文本包含[n1]
、[k1]
等TTS发音辅助标识,可参考以下方法进行过滤消除。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class TTSUtil {
static String REPLACE_NULL = "";
static String REGEX_TTS_ASSIST_TAG = "\\[[a-z]\\d\\]";
public static void main(String[] args) {
System.out.println(removeTTSAssistTag("The [a1] dog says meow."));
}
public static String removeTTSAssistTag(String text){
Pattern regex = Pattern.compile(REGEX_TTS_ASSIST_TAG);
Matcher input = regex.matcher(text);
text = input.replaceAll(REPLACE_NULL);
return text;
}
}