2D数字人交互SDK-Android版
一、产品介绍
提供端渲染交互SDK-2D小样本数字人,可以通过文本或PCM音频数据完成对虚拟人实时驱动。
1、适用场景特点
部署成本低: 支持低成本快速集成,人像渲染及唇形推理无需依赖云端服务;
网络依赖小:可落地在金融、政务等多种场景,适用线下硬件设备。
2、核心功能
公共形象租赁:提供半身、全身的2D小样本数字人形象,覆盖多种场景,支持客户快速集成使用;
专属形象定制:支持定制专属的2D小样本数字人形象;
实时播报渲染:支持数字人实时播报,可应用在多种线下终端设备对话问答场景;
性能指标:在3588及以上性能设备。
3、SDK下载链接
4、SDK的详细使用
4.1、在初始化页面:
第一次进入demo之后,请填写appKey、seceretKey和时长包,如需文本驱动请填写ttsId和ttsKey,然后先点击确认使用按钮(注意:时长包的确认使用,如果已经续期成功就不用点击了),再点击初始化SDK按钮,最后点击SDK授权+启动数字人(SURFACEVIEW),其他按钮请不要点击了。
4.2、进入数字人页面:
有两种播报模式,一种是普通播报,一种是流式播报,可点击右上角进行切换(流式播报切换到普通播报之前,需要先关闭流式播报)。
4.2.1、普通播报
(1)播报功能的使用:
需要点击播放长文本或播报短文本或播放PCM,其中文本驱动是播放长文本和播报短文本,播放PCM播放的是本地PCM文件。
普通播报一次只可播报一条数据(在语音播报期间不可以点击点击播放长文本或播报短文本或播放PCM),可以插入播报,插入播报有插入PCM播报和插入TXT播报(注意:如未播报语音,插入pcm播报会失败的),插入的播报会立即在当前播报中插入播报。
(2)切换形象:如需切换其他形象必须要有一个定制的形象包《具体可参考本文档8.1、定制人像包替换本地数字人像包》(注意:在播报中不可切换形象)。
(3)暂停/继续播报:暂停播报可使正在播报的播报暂停,继续播报可使已经暂停的播报恢复播报。
(4)打断播报:打断播报可使所有的普通播报(包括插入的所有播报)停止,且不可恢复。
(5)能力释放:可释放资源并且退出数字人页面。
注意:语音播报期间不可以点击点击播放长文本或播报短文本或播放PCM。
4.2.2、流式播报
流式播报就是可持续的播报,可把新的播报追加到当前播报后边
(1)播报功能的使用:首先点击打开流式播报按钮打开流式播报,流式播报需要点击持续PCM或持续TXT,其中文本驱动是持续TXT,持续PCM播放的是本地PCM文件。
流式播报就是可持续的播报,可以持续播报多条数据,就是把新的播报追加到当前播报后边(在播报期间点击持续PCM或持续TXT就是把新的PCM播报或TXT播报追加在当前播报的后边进行播报了)。
在语音播报期间可以插入播报,插入播报的时候需要点击开始插播按钮,这时开始插播按钮变成停止插播按钮了(插播期间不支持点击持续PCM和持续TXT按钮,请勿在插播期间进行持续播报),当前播报就暂停了,插入播报有插入PCM播报和插入TXT播报,插入的播报会立即播报出来,当不需要插播的时候,点击停止插播按钮,这时可以点击持续PCM和持续TXT按钮追加播报了。
(2)切换形象:如需切换其他形象必须要有一个定制的形象包《具体可参考本文档8.1、定制人像包替换本地数字人像包》(注意:在播报中不可切换形象)。
(3)暂停/继续播报:暂停播报可使正在播报的播报暂停,继续播报可使已经暂停的播报恢复播报。
(4)打断播报:打断播报可使所有的流式播报(包括插入的所有播报)停止,不可恢复。
(5)能力释放:可释放资源并且退出数字人页面。
注意:插播期间不支持点击持续PCM和持续TXT按钮,请勿在插播期间进行持续播报。
二、SDK集成
1、支持的系统和硬件版本
请注意:这是对于开发人员来说的,请开发人员按照此要求进行集成
建议rk3588及以上性能安卓板卡
系统 | 支持Android 7.0+(API Level 24)及以上 |
---|---|
CPU架构 | armeabi-v7a, arm64-v8a |
硬件要求 | 性能要求:硬件设备CPU 8核及以上,内存8G及以上,可用存储空间500MB及以上。 |
网络 | 支持WIF及移动网络。如果使用云端TTS(以文本方式驱动数字人),设备带宽(用于数字人的实际带宽)期望10mbps及以上。 |
开发IDE | Android Studio Flamingo 2022.2.1 Patch 1 |
内存要求 | SDK可用于数字人的内存 >= 400MB |
2、SDK集成
引入sdk aar 包:module_core-jnidev-release.aar,module_virtual-release.aar
2.1、app目录新建libs目录,放入aar包,在build.gradle中增加配置如下
1 implementation fileTree(dir: "libs", include: ["*.jar"])
2 implementation files('libs/module_core-jnidev-release.aar')
3 implementation files('libs/module_virtual-release.aar')
4
5 implementation 'com.google.code.gson:gson:2.8.9'
6 implementation("com.squareup.okhttp3:okhttp:4.11.0")
2.2、android studio 配置
2.2.1、设置-> Build, Execution, Deployment-> Build Tools -> Grale -> Gradle JDK, 设置java 11
2.2.2、工程设置(mac 下,快捷键commond+;)Android Gradle plugin Verison
2.2.3、Android SDK & java 版本设置
以下配置为建议配置,其他版本可能存在问题。
3、系统权限配置以及申请
3.1、权限配置
1<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
2<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
3<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
5<uses-permission android:name="android.permission.INTERNET" />
6<uses-permission android:name="android.permission.READ_PHONE_STATE" />
7<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
8<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
9<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
3.2、权限申请
请参考demo BaseActivity示例,所列举的权限为最低权限要求,如果缺少某一个,会导致sdk出现异常。
三、SDK调用及API说明
1、初始化相关
1.1、初始化SDK- 设备授权
初始化是指数字人资源以及形象资源初始化, 调用方式参考接口相关文档
appKey、seceretKey为一台设备独有,一个设备要使用数字人必须要有一对appKey、seceretKey,使用这两个参数就可以使用音频驱动了。
如需文本驱动,就必须要有一对ttsId、ttsKey,ttsId和ttsKey为组件平台创建的tts合成应用的appId和appKey,
tts音色参考:https://cloud.baidu.com/doc/AI_DH/s/plyy6xhi0。
1int init(Context context, VirtualInitParam virtualInitParam);
参数说明:
参数名 | 取值 | 说明 |
---|---|---|
context | Context | 非空 |
virtualInitParam | VirtualInitParam | 非空 |
VirtualInitParam的4个参数说明
参数名 | 取值 | 说明 |
---|---|---|
appKey | appKey | 非空,这两个值,由百度提供,为一台设备的独有。请向百度申请。 |
seceretKey | seceretKey | |
ttsId | ttsId | 如需文本驱动,就必须要有一对ttsId、ttsKey。请在组件平台创建tts合成应用, 获取方式请参考文档:https://cloud.baidu.com/doc/AI_DH/s/plyy6xhi0。 |
ttsKey | ttsKey |
返回参数说明:
code | 说明 |
---|---|
0 | 初始化成功 |
-1000 | Context为null |
-1001 | AppKey为空 |
-1002 | SecretKey为空 |
-1003 | AppKey长度错误 |
-1004 | SecretKey长度错误 |
-1005 | 设置文件路径失败 |
-1006 | 引擎状态错误,重复初始化 |
-1007 | callback为null |
-1008 | 项目授权请求结果错误 |
-1009 | ProjectAK为空 |
-1010 | ProjectSK为空 |
-1011 | ProjectAK长度错误 |
-1012 | ProjectSK长度错误 |
-1013 | 项目授权时Context为null |
-1014 | 项目授权时VirtualAuth为null |
-1015 | VirtualInitParam为空 |
-1016 | ttsid为空 |
-1017 | ttsKey为空 |
调用示例
1public class MainApplication extends Application {
2 @Override
3 protected void attachBaseContext(Context base) {
4 super.attachBaseContext(base);
5 VirtualFactory.getEngine().init(this, Config.APP_KEY, Config.SECERET_KEY);
6 }
7}
1.2、获取自定义模型地址
用于获取非内置模型文件地址, 1、通过该接口获取地址,2、将所需模型推送至该地址目录下
1String getThirdVirtualModelPath()
调用示例
1String modelPath = VirtualFactory.getEngine().getThirdVirtualModelPath()
1.3、更新ttsId和ttsKey参数
ttsId和ttsKey为组件平台创建的tts合成应用的appId和appKey,
获取方式请参考文档:https://cloud.baidu.com/doc/AI_DH/s/plyy6xhi0。
1boolean updateTtsParam(String ttsId, String ttsKey);
参数说明:
参数名 | 取值 | 说明 |
---|---|---|
ttsId | ttsId | 如需文本驱动,就必须要有一对ttsId、ttsKey。请在组件平台创建tts合成应用, 获取方式请参考文档:https://cloud.baidu.com/doc/AI_DH/s/plyy6xhi0。 |
ttsKey | ttsKey |
调用示例
1VirtualFactory.getEngine().updateTtsParam(ttsId, ttsKey);
2、SDK授权
授权是针对数字人功能能力授权,如果不授权或者授权不通过将无法使用数字人功能,授权方式可参考文档
2.1、获取SDK授权状态
1public synchronized boolean getOauthState(final Context context, final AuthStateCallBack authStateCallback)
参数说明
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
authStateCallback | AuthStateCallBack | code:0:成功,其他:失败 subCode: 后端返回状态码 activeTime:生效时间,异常时返回0 expirationTime:到期时间,异常时返回0 msg: 提示消息 |
subCode为后端返回状态码。由于该码可能会有变动,所以不可作为业务逻辑判断使用 |
返回值 | boolean | true: 获取成功 false:获取失败 |
code取值:
code | 说明 |
---|---|
0 | 续期成功 |
-1001 | 获取状态失败,SDK状态异常 |
-1002 | 获取状态失败,后台返回为空 |
-1003 | 获取状态失败,后台状态不成功 |
-1004 | 获取状态失败,没有返回license |
-1005 | 获取状态失败,一般是网络异常 |
调用示例
1VirtualAuth vhAuth = new VirtualAuth()
2vhAuth.getOauthState(mContext, (code, subCode, activeTime, expirationTime, msg) -> {
3 // 相关业务处理逻辑
4 });
2.2、使用时长码
当使用新的 appKey,seceretKey 时必须进行激活,激活方式为使用时长码激活,时长码会随着appKey,seceretKey 提供,使用项目授权方式时不需要时长码激活。
1public synchronized boolean renewExpirationDate(final Context context, String activateCode,
2 final AuthRenewCallBack renewCallBack)
参数定义:
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 非空 | |
activateCode | String | 非空 | 有效的激活码 |
renewCallBack | AuthRenewCallBack | code:0:成功,其他:失败 subCode:后端返回状态码 expirationTime:有效的时候取有效值,异常时返回0 msg: 提示消息 |
subCode为后端返回状态码。由于该码可能会有变动,所以不可作为业务逻辑判断使用 |
返回值 | boolean | true: 获取成功 false:获取失败 |
code取值如下:
取值 | 说明 |
---|---|
0 | 续期成功 |
-1000 | 续期失败,发生异常 |
-1001 | 续期失败,SDK状态异常 |
-1002 | 续期失败,后台返回为空 |
-1003 | 续期失败,后台状态不成功 |
调用示例
1VirtualAuth vhAuth = new VirtualAuth()
2vhAuth.renewExpirationDate(mContext, inputCode, (code, subCode, expirationTime, msg) -> {
3
4 });
2.3、SDK授权初始化
数字人能力授权, 成功后可执行数字人相关逻辑
1public synchronized boolean initLicenseBatch(final Context context, final AuthCallBack authCallback)
参数说明
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
authCallback | AuthCallBack | code:0:成功,其他:失败 subCode:后端返回状态码 msg: 提示消息 |
subCode为后端返回状态码。由于该码可能会有变动,所以不可作为业务逻辑判断使用 |
code取值(目前取值如下,未来会增加):
取值 | 说明 |
---|---|
0 | 授权成功 |
-1000 | 授权失败 |
-1001 | tts授权失败 |
-1002 | 设备ID失败 |
-1003 | 引擎状态异常 |
-1004 | 模型文件异常 |
调用示例
1VirtualAuth vhAuth = new VirtualAuth()
2vhAuth.initLicenseBatch(mContext, (code, subCode, msg) -> {
3
4 });
2.4、换绑授权码设备
当一个授权码还存在有效期,但是设备坏了的情况下,可以使用这个接口进行授权设备的换绑,使用项目授权方式时不可进行换绑。
换绑接口有次数限制,非特殊情况不宜调用
1public synchronized boolean changeDeviceBind(final Context context, final AuthStateCallBack callBack)
参数说明
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
callBack | AuthStateCallBack | code:0:成功,其他:失败 subCode:后端返回状态码 msg: 提示消息 |
subCode为后端返回状态码。由于该码可能会有变动,所以不可作为业务逻辑判断使用 |
code取值
取值 | 说明 |
---|---|
0 | 授权成功 |
-1001 | 切换失败,SDK状态异常 |
-1002 | 切换失败,后台返回为空 |
-1003 | 切换失败,后台状态不成功 |
-1004 | 切换失败,一般是网络异常(也可能是调用方代码异常了) |
调用示例
1VirtualAuth vhAuth = new VirtualAuth()
2vhAuth.changeDeviceBind(mContext, (code, subCode, msg) -> {
3
4 });
3、数字人形象
数字人是通过Player 对象进行管理, 每次初始化要求为一个Player对象,用于调用数字人相关操作接口,具体接口参考接口文档,数字人显示部分可参考demo MainActivity.java 示例代码
静默态说明: 当开启静默态时(isCloseSilent = false)未进行播报时可以展示形象和背景;
当未开启静默态时(isCloseSilent = true)未播报时不会展示形象和背景,播报时会展示形象和背景,播报完成后会定在最后一帧,如果这时退出后台再次进入则会进入默认态(不会展示形象和背景)
3.1、数字人形象初始化
surface 模式初始化流程
3.1.1、初始化Player
请注意:初始化Player后,请先设置数字人形象《具体可参考本文档3.1.5、设置数字人形象》。
1public static Player getPlayer(Context context)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
返回值 | Player | 用于Player 相关接口后续调用 |
调用示例
1Player player = VirtualFactory.getPlayer(mContext);
3.1.2、设置背景图
如果需要背景为透明状态则无需调用此接口设置背景,直接参考 3.1.3 设置即可
1boolean setBackground(Bitmap bitmap)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
bitmap | Bitmap | 背景图片 |
调用示例
1player.setBackground(BitmapFactory.decodeResource(getResources(), R.mipmap.back));
3.1.3、设置数字人背景透明
直接设置SurfaceView 为透明状态即可
1mSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
2 mSurfaceView.setZOrderOnTop(true);
3.1.4、添加player 消息回调
1boolean addCallback(Callback callback);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
callback | Callback | 设置回调 |
Callback 回调说明
参数名 | 取值 | 说明 |
---|---|---|
void onVirtualHumanStart() | 数字人播放开始 | |
void onVirtualHumanFinish() | 数字人播放结束 | |
void onVirtualHumanData(VirtualHumanDataBean frameBean) | frameBean.getAudioStreams() PCM 音频数据 frameBean.getVideoStreams() 数字人形象RGBA 数据 |
数字人音频数据和形象RGBA 数据, 使用前需做判空处理 |
void onRemainBuffer(int remainBytes, intremainInsertBytes) | remainBytes: 剩余未播放的buffer remainInsertBytes: 剩余未播放插播的buffer数据 |
数字人剩余未播放的buffer长度 |
void onVirtualHumanPause() | 暂停播放 | |
void onPcmVolumeError(int code, String message, float vol) | code: -1:扩大失败 message: 错误信息 vol: 1倍-10倍 :当前设置的倍数 |
幅值放大后出现截幅失真会进行触发 |
void onError(int code, intsubCode, String msg) | code:-1000:tts数据异常 -1001: 播放器状态不合适 subCode: 详情参考 7.3错误信息参数说明 msg: 错误信息 |
出错消息 |
调用示例
1player.addCallback(new Player.Callback() {
2 @Override
3 public void onVirtualHumanStart() {
4
5 }
6
7 @Override
8 public void onVirtualHumanFinish() {
9
10 }
11
12 @Override
13 public void onVirtualHumanData(VirtualHumanDataBean frameBean) {
14
15 }
16
17 @Override
18 public void onRemainBuffer(int remainBytes, int remainInsertBytes) {
19
20 }
21
22 @Override
23 public void onPcmVolumeError(int code, String message, float vol) {
24
25 }
26
27 @Override
28 public void onVirtualHumanPause() {
29
30 }
31
32 @Override
33 public void onError(int code, int subCode, String msg) {
34
35 }
36 });
3.1.5、设置数字人形象
1void setVirtualModel(Model model, DisplayMode displayMode, ChangeVirtualModelCallback callback)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
model | Model | visualize:形象ID,visualize值默认是10001,内置的默认人像是"慕晴",如加载定制人像包,visualize值则要大于0且不等于20,也不能等于10001-11000中的数,还不能重复,visualize值为数字人像包中的文件夹名字《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 figureId: 人像资源ID,定制人像资源必须传非null值,只有默认人像(目前是10001)可以传null,该值是调用生成人像的API接口返回的,figureId就是下载的人像包文件夹内的sdk.info文件里的figure值《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 isCloseAudio:true:关闭声音; false:打开声音(默认) isCloseSilent:true:关闭静默态; false: 打开静默态(默认) |
人像模型 |
displayMode | DisplayMode | RENDER_ONLY: surface模式 |
|
callback | ChangeVirtualModelCallback | code:0:成功,其他:失败 subCode:code非0时,可能会有非0的取值 msg: 提示消息 |
code、subCode 参考7.3、错误信息参数说明 |
调用示例
1Model model = new Model(useVirtualId);
2DisplayMode displayMode = new DisplayMode();
3displayMode.setDataMode(DisplayMode.DataMode.RENDER_ONLY); // surface模式
4player.setVirtualModel(model, displayMode, (msgType, msgSubType, msg) -> {
5
6 });
3.1.6、文本转PCM 回调
非必需函数, 如果需要txt相关信息则添加该回调即可
1boolean setPlayTxtCallback(TxtPlayCallback callback)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
callback | TxtPlayCallback | code: 错误码 subCode: txtSn:txt的唯一标志,调用文本播放时自动生成该文本的唯一表示 msg:错误信息 |
调用示例
1player.setPlayTxtCallback(new Player.TxtPlayCallback() {
2 @Override
3 public void onTtsToPcm(int code, int subCode, String txtSn, String msg) {
4
5 }
6 });
3.1.7、形象模型MD5 校验
非必需函数, 如果校验模型完整性时调用
1void virtualModelCheck(Model model, VirtualModelCheckCallback callback);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
model | Model | visualize:形象ID,visualize值默认是10001,内置的默认人像是"慕晴",如加载定制人像包,visualize值则要大于0且不等于20,也不能等于10001-11000中的数,还不能重复,visualize值为数字人像包中的文件夹名字《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 figureId: 人像资源ID,定制人像资源必须传非null值,只有默认人像(目前是10001)可以传null,该值是调用生成人像的API接口返回的,figureId就是下载的人像包文件夹内的sdk.info文件里的figure值《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 |
人像模型 |
callback | VirtualModelCheckCallback | code:0:成功,其他:失败 subCode:code非0时,可能会有非0的取值 msg: 提示消息 |
调用示例
1Model model = new Model(useVirtualId);
2 player.virtualModelCheck(model, new Player.VirtualModelCheckCallback() {
3 @Override
4 public void onVirtualModelCheckStatus(int code, int subCode, String msg) {
5
6 }
7 });
3.2、数字人形象启动
3.2.1、设置显示解码
1boolean setDisplay(Surface surface, int width, int height)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
surface | Surface | 展示形象的surface | |
width | int | 展示形象的宽 | |
height | int | 展示形象的高 | |
返回值 | boolean | 如果surface为空,返回false |
调用示例
1/**
2 * Surface 模式下
3 */
4 @Override
5 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
6 player.setDisplay(holder.getSurface(), width, height);
7 }
3.2.2、形象展示
1void onResume()
调用示例
1 @Override
2 protected void onResume() {
3 player.onResume();
4 super.onResume();
5 }
3.3、数字人形象暂停
1void onPause();
调用示例
1 @Override
2 protected void onPause() {
3 player.onPause();
4 super.onPause();
5 }
3.4、数字人形象切换
注意事项1:Surface 模式在进入人像页面后支持720p切换720p,也支持1080p切换1080p。此外,如果想从720p切换到1080p或从1080p切换到720p,需要重新初始化SDK和重新加载人像。
注意事项2:如果不想使用默认人像,想直接使用定制人像,请先参考本文档的8.1、定制数字人像包替换本地数字人像包《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》,然后重新初始化SDK和重新加载人像(定制人像B替换本地人像A,则需要重新加载一次,定制人像C替换定制人像B也需要重新加载一次),重新加载人像需要在执行demo的MainActivity的initPlayer方法的player.setVirtualModel方法前,初始化定制人像的Model,初始化方法是Model model = new Model(visualize, figureId),参数说明请参考本文档3.4、数字人形象切换《具体可参考本文档3.4、数字人形象切换》表格的Model说明。
1void changeVirtualModel(Model model, ChangeVirtualModelCallback callback)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
model | Model | visualize:形象ID,visualize值默认是10001,内置的默认人像是"慕晴",如加载定制人像包,visualize值则要大于0且不等于20,也不能等于10001-11000中的数,还不能重复,visualize值为数字人像包中的文件夹名字《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 figureId: 人像资源ID,定制人像资源必须传非null值,只有默认人像(目前是10001)可以传null,该值是调用生成人像的API接口返回的,figureId就是下载的人像包文件夹内的sdk.info文件里的figure值《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 |
人像模型 |
callback | ChangeVirtualModelCallback | code:0:成功,其他:失败 subCode:code非0时,可能会有非0的取值 msg: 提示消息 |
code、subCode 参考7.3、错误信息参数说明 |
调用示例
1 Model model = new Model(useVirtualId);
2 // Model model = new Model(useVirtualId, figureId);
3 player.changeVirtualModel(model, (code, subCode, msg) -> {
4
5 });
3.5、数字人形象释放
1、surface模式下释放接口需在view销毁完成后进行调用; 例如: 有一个surface view, 需要在surface view 执行surfaceDestroyed 回调内进行调用release() 方法
1void release();
调用示例
1/**
2 * 移除surfaceView
3 */
4 ViewGroup parent = (ViewGroup) mSurfaceView.getParent();
5 parent.removeView(mSurfaceView);
6 mSurfaceView.getHolder().getSurface().release();
7 mSurfaceView = null;
8
9 /**
10 * surfaceDestroyed 内执行release方法
11 */
12 @Override
13 public void surfaceDestroyed(SurfaceHolder holder) {
14 player.release();
15 finish();
16 }
4、普通模式驱动数字人
普通模式下播报数据,与流式模式下不同的是流式模式可持续播报而普通模式单次只可播报一条数据,具体调用参考接口文档
4.1、PCM播报
注意pcm的格式(单声道,16k,16bit)。播放buffer最大只支持10分钟,大约72MB。插播最大3分钟的数据,大约21.9MB;byte[]长度需大于16000,小于16000 x (16 / 8)x 30x20
1boolean speakWithPcm(Context context, int[][] actions, byte[] bytes);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
actions | int[][] | {0, 0} 默认值 | 播报文本动作,目前不支持文本动作设置 |
bytes | byte[] | pcm数据, 格式要求:16000hz,单声道,16位 | |
返回值 | boolean | true: pcm数据设置成功 false: pcm 数据设置失败 |
调用示例
1byte[] pcmBytes = FileUtils.getByte(pcmPath + "input/1_16.pcm");
2player.speakWithPcm(mContext, new int[][]{{1,10}}, pcmBytes);
4.2、文本播报
需要注意的是,当SDK启动后,第一次speak一段文本时,需要请求网络,请保证设备的网络正常。在sdk不重启的情况,如果一段文字请求过,则会缓存在内存中,不再请求网络,这样会占用一部分内存。需要注意pcm的格式(单声道,16k,16bit)。播放buffer最大只支持10分钟,大约72MB。插播最大3分钟的数据,大约21.9MB。
默认txt最大为520个字符,对于需要超过这个长度文本,请和百度方沟通。
1PlayTxtResult speakWithTxt(Context context, String stext, int[][] actions, SpeakerConf conf);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
stext | String | 播报文本信息。 当使用LITE版克隆音色及公共音色库中支持多语言的音色时,支持自动识别输入语言来进行播报。例:当输入俄文时,使用俄语播报。 |
|
conf | SpeakerConf | 设置音库, 具体参数请参考 7.2 SpeakerConf 参数 | |
返回值 | PlayTxtResult | 该文本的唯一标识和执行结果 |
调用示例
1player.speakWithTxt(mContext, "你好,我是百度数字人。百度(Baidu)是拥有强大互联网基础的领先AI公司。" +
2 "百度愿景是:成为最懂用户,并能帮助人们成长的全球顶级高科技公司。“百度”二字," +
3 "来自于八百年前南宋词人辛弃疾的一句词:众里寻他千百度。", new int[][]{{1, 10}},
4 SpeakerConf.builder());
4.3、PCM 插播
1boolean speakInsertOnFlowPcm(Context context, byte[] bytes)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
bytes | byte[] | 需要插播的pcm数据 | |
返回值 | boolean | true: 插播pcm数据设置成功 false:插播pcm 数据设置失败 |
调用示例
1byte[] pcmBytes = FileUtils.getByte(pcmPath + "input/1.pcm");
2boolean ret = player.speakInsertOnFlowPcm(mContext, pcmBytes);
4.4、文本插播
1PlayTxtResult speakInsertTxt(Context context, String stext, SpeakerConf conf)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
stext | String | 需要插播的文本数据 | |
conf | SpeakerConf | 设置音库, 具体参数请参考 7.2 SpeakerConf 参数 | |
返回值 | PlayTxtResult | 该文本的唯一标识和执行结果 |
调用示例
1PlayTxtResult result = player.speakInsertTxt(mContext,
2 "你好啊,虽然我不认识您,但是相逢就是有缘,欢迎来到直播间~老铁~",
3 SpeakerConf.builder().setPerson(Config.sTtsPerson));
4.5、暂停播报
1boolean pausePlay()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停播放 false:停止异常 |
如果已经停止的状态,也会返回true |
调用示例
1player.pausePlay();
4.6、继续播报
1boolean resumePlay()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停播放 false:停止异常 |
如果已经停止的状态,也会返回true |
调用示例
1player.resumePlay();
4.7、打断播报
打断当前正在进行播报包含插播数据, 打断后不可恢复
1void interrupt()
调用示例
1player.interrupt();
4.8、是否正在播放中
用于播放状态判断
1boolean isPlaying()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 正在播放中 false:停止播放 |
调用示例
1player.isPlaying()
4.9、是否在暂停状态
用于播放状态判断
1boolean isPause()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停状态 false:非暂停状态 |
调用示例
1player.isPause()
4.10、设置播报音量
按需使用,该能力仅用于音频数据本身较小、存在数学放大条件的前提下可用,若音频原始数据幅值已经过大(最大值参考:-32768~ 32768 ),请使用硬件方式进行功率放大,代码中该能力不可用;
错误信息参考 3.1.4、添加player消息回调中的onPcmVolumeError回调
1void setPcmVolume(float vol)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
vol | float | 默认值为1,范围[1~10] |
调用示例
1player.setPcmVolume(1);
5、流式模式驱动数字人
开启流式播报后可以持续播报数据,与普通模式下不同的是普通模式只能单条播报而流式可持续播报,详细使用可参考本文档4.2.2、流式播报《具体可参考本文档4.2.2、流式播报》,具体调用参考接口文档
需要注意pcm的格式(单声道,16k,16bit);播放buffer最大只支持10分钟,大约72MB。每次调用speakFlowOnPcm时byte[]的长度需大于16000,开启降噪时需保证降噪后的有效音频byte[]长度大于16000
5.1、开启流式播报
5.1.1、不需要噪音抑制功能
1boolean speakFlowStart(Context context)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
返回值 | boolean | true: 开启成功 false:开启失败 |
调用示例
1player.speakFlowStart(mContext);
5.1.2、需要噪音抑制功能
1boolean speakFlowStart(Context context, boolean startNoiseSuppressor)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
startNoiseSuppressor | boolean | true: 开启噪音抑制 false:不开启噪音抑制 |
是否开启噪音抑制 |
返回值 | boolean | true: 暂停状态 false:非暂停状态 |
调用示例
1player.speakFlowStart(mContext, true);
5.2、关闭流式播报
1boolean speakFlowFinish(Context context)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
返回值 | boolean | true: 暂停状态 false:非暂停状态 |
调用示例
1player.speakFlowFinish(mContext);
5.3、流式PCM播报
1boolean speakFlowOnPcm(Context context, byte[] bytes)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
bytes | byte[] | 需要插播的pcm数据 | |
返回值 | boolean | true:PCM 数据设置成功 false: PCM 数据设置失败 |
调用示例
1byte[] pcmBytes = FileUtils.getByte(pcmPath + "input/1_16.pcm");
2player.speakFlowOnPcm(mContext, pcmBytes);
5.4、流式TXT播报
1PlayTxtResult speakFlowOnSegTxt(Context context, String segTxt, SpeakerConf conf)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
segTxt | String | 需要插播的文本数据 | |
conf | SpeakerConf | 设置音库, 具体参数请参考 7.2 SpeakerConf 参数 | |
返回值 | PlayTxtResult | 该文本的唯一标识和执行结果 |
调用示例
1PlayTxtResult result = player.speakFlowOnSegTxt(mContext, "你好,我是百度数字人。百度(Baidu)是拥有强大互联网基础的领先AI公司。百度愿景是:"+
2 "成为最懂用户,并能帮助人们成长的全球顶级高科技公司。“百度”二字,来自于八百年前南宋词人辛弃疾的一句词:"+
3 "众里寻他千百度。",SpeakerConf.builder().setPerson(Config.sTtsPerson));
5.5、开始流式插播
开启插播后进入插播模式,需要调用关闭插播接口进行退出插播模式
1boolean speakInsertFlowPcmStart(Context context)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
返回值 | boolean | rue: 开启插播正常 false:开启插播异常, 可能未处于流式播报模式 |
调用示例
1player.speakInsertFlowPcmStart(mContext)
5.6、关闭流式插播
1boolean speakInsertFlowPcmFinish(Context context, boolean isFnishInsertPcm)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
isFnishInsertPcm | boolean | true: 播放完之前已经插入的数据 false: 直接停止,回到插播前的内容上 (默认) |
是否停止插入PCM数据 |
返回值 | boolean | true: 关闭插播正常 false:关闭插播异常,可能未开启插播模式 |
调用示例
1player.speakInsertFlowPcmFinish(mContext, true);
5.7、流式PCM插播
1、如果未开启插播模式,可以支持插播,插播完毕后继续播放正文;如果开启插播则处于插播模式当中,需要调用关闭插播接口,退出插播模式后继续播报正文
2、需要注意pcm的格式(单声道16k; 16bit)。插播最大3分钟的数据,大约21.9MB。
1boolean speakInsertOnFlowPcm(Context context, byte[] bytes)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
bytes | byte[] | 需要插播的pcm数据 | |
返回值 | boolean | true: 插播pcm数据设置成功 false:插播pcm 数据设置失败 |
调用示例
1byte[] pcmBytes = FileUtils.getByte(pcmPath + "input/1.pcm");
2boolean ret = player.speakInsertOnFlowPcm(mContext, pcmBytes);
5.8、流式TXT插播
1、如果未开启插播模式,可以支持插播,插播完毕后继续播放正文;如果开启插播则处于插播模式当中,需要调用关闭插播接口,退出插播模式后继续播报正文
1PlayTxtResult speakInsertTxt(Context context, String stext, SpeakerConf conf)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
context | Context | 上下文 | |
stext | String | 需要插播的文本数据 | |
conf | SpeakerConf | 设置音库, 具体参数请参考 7.2 SpeakerConf 参数 | |
返回值 | PlayTxtResult | 该文本的唯一标识和执行结果 |
调用示例
1PlayTxtResult result = player.speakInsertTxt(mContext,
2 "你好啊,虽然我不认识您,但是相逢就是有缘,欢迎来到直播间~老铁~",
3 SpeakerConf.builder().setPerson(Config.sTtsPerson));
5.9、暂停播报
1boolean pausePlay()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停播放 false:停止异常 |
如果已经停止的状态,也会返回true |
调用示例
1player.pausePlay();
5.10、继续播报
1boolean resumePlay()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停播放 false:停止异常 |
如果已经停止的状态,也会返回true |
调用示例
1player.resumePlay();
5.11、打断播报
打断当前正在进行播报包含插播数据, 打断后不可恢复
1void interrupt()
调用示例
1player.interrupt()
5.12、是否正在播放中
用于播放状态判断
1boolean isPlaying()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 正在播放中 false:停止播放 |
调用示例
1player.isPlaying()
5.13、是否在暂停状态
用于播放状态判断
1boolean isPause()
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
返回值 | boolean | true: 暂停状态 false:非暂停状态 |
调用示例
1player.isPause()
5.14、设置播报音量
按需使用,该能力仅用于音频数据本身较小、存在数学放大条件的前提下可用,若音频原始数据幅值已经过大(最大值参考:-32768 ~ 32768 ),请使用硬件方式进行功率放大,代码中该能力不可用;
错误信息参考 3.1.4、添加player消息回调中的onPcmVolumeError回调
1void setPcmVolume(float vol)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
vol | float | 默认值为1,范围[1~10] |
调用示例
1player.setPcmVolume(1);
6、文本处理
player获取方式参考 3.1、数字人形象初始化
6.1、预加载文本的pcm数据
1boolean preLoadTxtPcm(String segTxt, SpeakerConf conf, TtsPcmDataCallback dataCallback)
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
segTxt | String | 文本信息 | |
conf | SpeakerConf | 设置音库, 详情参数请参考 7.2、SpeakerConf 参数 | |
callback | TtsPcmDataCallback | code:0:成功,其他:失败 subCode:code非0时,可能会有非0的取值 msg: 提示消息 bytes:pcm数据 |
文本转PCM后的回调 code、subCode 参考7.3、错误信息参数说明 |
调用示例
1player.preLoadTxtPcm(txt, SpeakerConf.builder().setPerson(Config.sTtsPerson), new Player.TtsPcmDataCallback() {
2 @Override
3 public void onTtsPcmData(int code, int subCode, String msg, byte[] bytes) {
4
5 }
6});
6.2、设置预加载pcm的缓存空间的大小
1void setPreLoadPcmCacheSize(int size);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
size | int | 取值范围【0 ~ 2048】,默认:1024 | 单位: MB |
调用示例
1player.setPreLoadPcmCacheSize(1024);
6.3、删除文本预加载时缓存的所有文件
1void clearCache();
调用示例如下:
1TtsCacher.instance().clearCache();
6.4、删除文本预加载时缓存的某一个文件
1void clearTxtCache(String txt, SpeakerConf conf) ;
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
txt | String | 需要删除的文本信息 | |
conf | SpeakerConf | 设置音库, 详情参数请参考 7.2、SpeakerConf 参数 |
调用示例如下:
1TtsCacher.instance().clearTxtCache("需要删除的文本信息", SpeakerConf.builder().setPerson(Config.sTtsPerson));
7、工具类
7.1、模型效验(包括文件完整性校验和文件版本校验)
1void checkModel(Model model, ModelCheck.ModelCheckCallback callback);
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
model | Model | visualize:形象ID,visualize值默认是10001,内置的默认人像是"慕晴",如加载定制人像包,visualize值则要大于0且不等于20,也不能等于10001-11000中的数,还不能重复,visualize值为数字人像包中的文件夹名字《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 figureId: 人像资源ID,定制人像资源必须传非null值,只有默认人像(目前是10001)可以传null,该值是调用生成人像的API接口返回的,figureId就是下载的人像包文件夹内的sdk.info文件里的figure值《具体可参考本文档8.1、定制数字人像包替换本地数字人像包》 |
人像模型 |
callback | ModelCheck.ModelCheckCallback | figureId: 人像资源id,调用生成人像的API接口返回的。内置的默认人像是"慕晴",传null code:参考7.3、错误信息参数说明 subCode: 参考7.3、错误信息参数说明 msg: 提示消息 |
code取值
取值 | 说明 |
---|---|
0 | 校验成功 |
-1000 | 检查失败,目录不存在 |
-1001 | 检查失败,版本信息文件不存在 |
-1002 | 检查失败,版本信息文件内容为空 |
-1003 | 检查失败,版本信息文件内容格式错误 |
-1004 | 检查失败,人像资源包版本过低 |
-1005 | 检查失败,默认模型init文件不存在 |
-1006 | 检查失败,后台返回为空 |
-1007 | 检查失败,后台状态不成功 |
-1008 | 检查失败,没有返回文件信息 |
-1009 | 检查失败,一般是网络异常 |
-1010 | 检查失败,模型文件个数为0 |
-1011 | 检查失败,init文件内容为空 |
-1012 | 检查失败,init文件中的文件个数为0 |
-1013 | 检查失败,init文件格式错误 |
-1014 | 检查失败,文件不匹配,文件缺失或被修改 |
-1015 | 检查失败,文件匹配对比时异常 |
调用示例
1VirtualModelUtil.checkModel(model, (figureId, code, subCode, msg) -> {
2
3 });
7.2、SpeakerConf 参数
需要注意的是,需要和百度方确认,per取值的范围
参数名 | 类型 | 取值 | 说明 |
---|---|---|---|
spd | int | 语速,取值0-15,默认为5中语速 | 语速 |
pit | int | 音调,取值0-15,默认为5中音调, 克隆音色暂不生效 | 音调 |
vol | int | 音量,取值0-15,默认为5中音量,克隆音色暂不生效 | 音量 |
aue | int | 6:wav(内容同pcm-16k)默认 | 音频格式 |
per | int | 默认:度小希=5116 更多音色请参考:https://cloud.baidu.com/doc/AI_DH/s/Slywt3fxy |
音色 |
7.3、错误信息参数说明
code | subCode | 参数含义 |
---|---|---|
0 | 0 | 成功 |
-1000 | -2000 | 参数错误 |
-2006 | 获取tts异常 | |
-2007 | tts 返回null | |
-1001 | -2001 | 重复设置模型 |
-2003 | 调用顺序异常 | |
-2005 | 正在播放中 | |
-2009 | 没有播报 | |
-1002 | -2002 | 形象包不存在 |
-2008 | 缓存已满 | |
-1003 | -2008 | 插播缓存已满 |
-1004 | -2004 | 数字人切换频繁 |
8、常见问题
8.1、定制人像包替换本地数字人像包
SDK支持定制人像包替换
- 命名定制人像包:
如使用定制人像包,则在初始化SDK之前需要下载对应的定制人像包压缩文件,定制人像包压缩文件解压后就是一个人像包文件夹,人像包文件夹需要改名字,用数字来命名(数字大于0且不等于20,也不能等于10001-11000中的数,还不能重复)。
- push路径:
把人像包文件夹push到设备的
/sdcard/baidu/aip/virtual_models/data/render_model路径内(此路径是定制人像包的路径,使用adb push命令把人像包文件夹push进去)。
- 使用方式:
定制人像包的路径会多一个文件夹,然后调用切换数字人方法可切换到此定制的数字人形象《具体可参考本文档3.4、数字人形象切换》。