本文介绍了如何使用硅基数字人服务提供的DUIX Android SDK,包括下载安装、关键接口及代码示例。
下载duix-cloud-demo_1.2.3.zip (opens new window)示例代码,使用Android Studio打开项目.
引入 aar 包: duix_cloud_sdk_release_${version}.aar
app 目录新建 libs 目录,放入 aar 包.
在 build.gradle 中增加配置如下:
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation "org.webrtc:google-webrtc:1.0.32006"
implementation 'com.auth0:java-jwt:3.18.1'
}
在AndroidManifest.xml
文件中添加如下权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 可选: 当会话支持多模态时,需要该权限打开摄像头 -->
<uses-permission android:name="android.permission.CAMERA" />
在项目的proguard-rules.pro文件中添加如下配置:
-keep class org.webrtc.**{ *; }
-keep class org.eclipse.paho.client.** { *; }
-keep class org.eclipse.paho.uri.** { *; }
在Activity中集成数字人模块代码, 如需使用麦克风,请确保启动前已经动态获取麦克风权限。
class DisplayActivity : BaseActivity() {
private var eglBaseContext = EglBase.create().eglBaseContext
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
binding.render.init(eglBaseContext, null)
binding.render.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
binding.render.setMirror(false)
binding.render.setEnableHardwareScaler(false /* enabled */)
binding.renderCamera.init(eglBaseContext, null)
binding.renderCamera.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
binding.renderCamera.setMirror(false)
binding.renderCamera.setEnableHardwareScaler(false /* enabled */)
VirtualFactory.init("your appId", "your appSecret")
player = VirtualFactory.getPlayer(mContext, eglBaseContext)
player?.addCallback(object : Player.Callback {
override fun onShow() {
Log.d(TAG, "onShow")
}
override fun onReady() {
Log.d(TAG, "onReady")
}
@SuppressLint("SetTextI18n")
override fun onError(msgType: Int, msgSubType: Int, msg: String?) {
runOnUiThread {
binding.tvMessage.visibility = View.VISIBLE
binding.tvMessage.text = "Session error: msgType: $msgType msgSubType: $msgSubType msg: $msg"
Log.e(
TAG,
"Session error: msgType: $msgType msgSubType: $msgSubType msg: $msg"
)
Toast.makeText(
mContext,
"Session error: msgType: $msgType msgSubType: $msgSubType msg: $msg",
Toast.LENGTH_SHORT
).show()
}
}
override fun onAsrResult(text: String?, sentenceEnd: Boolean) {
Log.e(TAG, "onAsrResult: $text, sentenceEnd: $sentenceEnd")
text?.let { showAsrResult(it, sentenceEnd) }
}
override fun onVideoTrack(
track: VideoTrack,
) {
runOnUiThread {
track.addSink(binding.render)
}
}
override fun onCameraTrack(track: VideoTrack) {
runOnUiThread {
track.addSink(localRenderer)
}
}
override fun onSessionInfo(duixBean: DUIXBean?) {
super.onSessionInfo(duixBean)
runOnUiThread {
binding.tvSwitchCamera.visibility = View.VISIBLE
binding.tvCloseCamera.visibility = View.VISIBLE
binding.tvOpenCamera.visibility = View.VISIBLE
}
}
})
player?.connect("your conversation id")
}
override fun onDestroy() {
super.onDestroy()
// Release resources
player?.release()
binding.render.release()
localRenderer?.release()
}
}
现在,您可以使用麦克风和数字人进行对话了。
使用平台账户中提供的appId和appSecret初始化模块并获取Play对象
VirtualFactory.init("your appId", "your appSecret")
player = VirtualFactory.getPlayer(mContext, eglBaseContext)
使用平台账号提供的conversationId连接数字人
player?.addCallback(callback)
player?.connect("your conversation id")
其中callback包含如下回调
onShow
数字人可以展示了void onShow();
onReady
数字人准备完毕void onShow();
onError
连接数字人发生异常void onError(int msgType, int msgSubType, String msg);
返回参数说明:
参数名 | 类型 | 说明 |
---|---|---|
msgType | int | 错误类型 |
msgSubType | int | 子错误类型 |
msg | String | 异常消息 |
其中msgType的取值:
取值 | 说明 | |
---|---|---|
1000 | 授权异常 | |
1001 | 创建会话异常 | |
1002 | 获取素材异常 | |
1010 | IM创建连接失败 | |
1011 | 渲染服务返回异常 | |
1020 | RTC 状态异常 | |
1030 | 渲染服务主动关闭 | |
1040 | IM连接丢失 | |
1050 | RTC连接丢失 |
onVideoTrack
RTC媒体通道创建成功在该回调中展示数字人控件绑定到track中
void onVideoTrack(VideoTrack track);
参数名 | 类型 | 说明 |
---|---|---|
track | VideoTrack | 视频媒体通道 |
onCameraTrack
Camera视频采集通道创建成功在该回调中展示摄像头媒体控件绑定到track中
void onCameraTrack(VideoTrack track);
参数名 | 类型 | 说明 |
---|---|---|
track | VideoTrack | 摄像头媒体通道 |
onAudioSamples
本地音频采集数据回调可在该回调中实现音频图像化等操作
default void onAudioSamples(int audioFormat, int channelCount, int sampleRat, byte[] data){}
onTtsSpeakStart
数字人开始播放TTS合成音频default void onTtsSpeakStart(){}
onTtsSpeakText
数字人播放TTS的文本内容default void onTtsSpeakText(String text){}
onTtsSpeakStop
TTS文本播放完成default void onTtsSpeakStop(){}
onSpeakStart
数字人开始播报default void onSpeakStart(){}
onSpeakText
数字人播报的文本内容default void onSpeakText(String text){}
onSpeakStop
数字人播报完成default void onSpeakStop(){}
onAsrResult
ASR识别内容回调default void onAsrResult(String text, boolean sentenceEnd){}
使用16k采样率16bit单通道的WAV音频地址驱动数字人说话
player?.speakWithWav(wavUrl, true)
参数名 | 类型 | 说明 |
---|---|---|
wavUrl | String | WAV音频的网络地址 |
interrupt | boolean | 是否打断当前说话状态 |
输入想要数字人想说的话,数字人会根据会话配置的音色说出对应的内容。
player?.speakWithTxt(text, true)
参数名 | 类型 | 说明 |
---|---|---|
text | String | 数字人的要说的文本内容 |
interrupt | boolean | 是否打断当前说话状态 |
让数字人来解答您的疑问。
player?.speakWithQuestion(text, true)
参数名 | 类型 | 说明 |
---|---|---|
text | String | 向数字人表达您的问题 |
interrupt | boolean | 是否打断当前说话状态 |
让数字人不要再说了
player?.stopAudio()
会话中翻转前后置摄象头(当开启多模态会话时可用)
player?.backFacing(isBackFacing)
会话中关闭摄象头(当开启多模态会话时可用)
player?.closeCamera()
会话中打开摄象头(当开启多模态会话时可用)
player?.openCamera()