星尘交互数字人Android SDK标准化文档
概述
星尘Xingchen-VideoChat-SDK是通义星尘推出的一个实时流媒体数字人Android SDK,具备低延迟、高性能、高并发、跨平台等优势, 结合阿里云的RTC、语音交互、渲染引擎、脸部和肢体驱动等技术,提供多种数字人解决方案,帮助企业和开发者快速集成数字人,打造数字人各种场景应用。
产品优势
高性能低延迟
轻松集成、标准化输出
产品能力
云端渲染数字人
云端渲染数字人是通过阿里云RTC提供视频流订阅,SDK在浏览器上拉取视频流呈现数字人的解决方案。
云端渲染数字人具备完整的语音交互、脸部和肢体驱动能力,提供数字人打断、多种对话模式。
接入前须知
云端渲染数字人、端测渲染(端到端)数字人的语音交互模式主要有三种模式:push2talk模式、tap2talk模式、duplex双工模式
在push2talk模式下,用户需要像类似钉钉发送语音消息那样,通过发送一段音频,来触发语音交互
在tap2talk模式下,SDK内部的语音服务会实时识别用户的语音输入。但是用户想打断数字人,需要通过额外事件来触发,比如点击屏幕,或者点击某按钮。
在duplex双工模式下,SDK内部的语音服务会实时识别用户的语音输入。数字人在说话状态下,仍可以接受用户的语音打断信号。
在duplex双工模式,容易受到外部环境音的影响导致触发频繁打断,请在相对安静的环境下使用双工模式。
星尘官网上的ApiKey并没有包含前缀Bearer 头,在初始化SDK的时候,请开发者自行添加前缀头,'Bearer ' + ApiKey, 具体可见如下示例项目中的代码或快速集成说明。
接入方法
Android Studio接入流程
下载示例工程及SDK aar
从OSS上下载VideoChatSdkDemo压缩包,并进行解压
环境配置
Gradle版本 8.0
Android Gradle Plugin 8.1.3
Jdk 17
Android Studio的版本要求,只要能支持上述三项的版本均可;其中Mac开发环境下建议使用以下版本
Android Studio Iguana | 2023.2.1 Patch 1
加载SDK和依赖,video_chat_sdk-release.aar在示例项目里
// aar直接依赖
implementation files('libs/video_chat_sdk-release.aar')
// OKHttp相关依赖
implementation("com.squareup.okhttp3:okhttp:4.10.0")
implementation("com.squareup.okio:okio:3.0.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.10.0")
权限相关
SDK和数字人交互需要用到录音权限,详细如下:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Release混淆处理
SDK中有部分实现类需要使用Json序列化传输,不能做混淆处理,上层应用编译Release版本时,需要把以下混淆规则补充进去
-keep class com.aliyun.allinone.** {
*;
}
-keep class com.aliyun.rts.network.** {
*;
}
-keep class com.aliyun.common.** {
*;
}
-keep class com.huawei.multimedia.alivc.** {
*;
}
-keep class com.alivc.rtc.** {
*;
}
-keep class com.alivc.component.** {
*;
}
-keep class org.webrtc.** {
*;
}
-keep class com.alibaba.ty.conv.** {
*;
}
-keep class com.tongyi.video_chat_sdk.TYVideoChat {
private static final *;
}
-dontwarn com.aliyun.aio.keep.API
-dontwarn com.aliyun.aio.keep.CalledByNative
-dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
-dontwarn org.conscrypt.*
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE
接口列表
API | 功能描述 |
init | 初始化方法,主要用来配置参数 |
start | 初始化成功后,启动对话流程 |
interrupt | 打断AI说话 |
startSpeech | Push2Talk模式 用户开始说话 |
stopSpeech | Push2Talk模式 用户结束说话 |
cancelSpeech | Push2Talk模式 用户取消说话 |
muteLocalMic | 是否关闭本地麦克风采集 |
requestToRespond | 请求服务端回答指定问题or做TTS播放出来 |
exit | 退出 |
接口详情
init
初始化SDK参数
/**
* 初始化方法,主要用来配置参数
* @param authParams RTC鉴权参数
* @param requestConfig 网关信息参数
* @return 初始化结果
*/
fun init(activity: Activity, authParams: TYRTCAuthParams, requestConfig: TYRequestConfig): Boolean
参数说明
参数名称 | 类型 | 是否必传 | 描述 |
activity | Activity | 是 | 活动实例 |
authParams | TYRTCAuthParams | 是 | 数字人配置参数 |
requestConfig | TYRequestConfig | 是 | 数字人鉴权的配置 |
其中TYRTCAuthParams为数字人配置参数,详细信息为
参数名称 | 类型 | 是否必传 | 描述 |
modelId | String | 是 | 模型Id,默认xingchen-plus-v2 |
voiceId | String | 是 | 音色Id,从星尘官网获取 |
avatarId | String | 是 | 数字人Id,从星尘官网获取 |
mode | TYVoiceChatMode | 是 | 对话模式,默认为tap2talk |
appId | String | 否 | 租户Id |
characterId | String | 否 | 个性id,和Content必须传一个,从星尘官网获取 |
content | String | 否 | 个性Content,和characterId必须传一个 |
userId | String | 是 | 业务自定义Id,保证唯一性即可,建议使用UUID赋值 |
useRtcAec | Boolean | 否 | 是否开启RTC内置AEC,默认开启 |
outboundSampleRate | Int | 否 | TTS音频采样率,默认为48000 |
extras | Map<String, Any> | 否 | 扩展消息 |
TYVoiceChatMode表示对话模式,是枚举类型,详细定义为
/**
* 会话模式
*/
object TYVoiceChatMode {
const val TAP2TALK = "tap2talk" // 默认方式,一方说完,另一方可以说话
const val PUSH2TALK = "push2talk" // 用户主动开始和结束说话
const val DUPLEX = "duplex" // 全双工模式,可语音打断
}
其中TYRequestConfig为数字人鉴权的配置参数,详细信息为
参数名称 | 类型 | 是否必传 | 描述 |
url | String | 是 | 鉴权地址,默认为https://nlp.aliyuncs.com/v2/api/videochat/initialize |
headers | Map<String,String> | 是 | 鉴权Headers,主要为从星尘官网获取的AppKey |
此处提供Init参考示例
注意点:Headers.Authorization中应包含"Bearer "+ ApiKey,ApiKey可以通过“星尘-我的空间-密钥管理”获取"
/*星尘网关示例 端上sdk可控制的参数*/
"authParams": {
// appId,当前不做校验,鉴权信息放在Header里
"appId": "",
// 数字人Id,必传
"avatarId": "video-chat-tianyou",
// 个性Id,当前不做校验,characterId和content必须传一个
"characterId": "123",
"content": "",
// 通话模式,必传
"mode": "tap2talk",
// LLM大模型ID,必传
"modelId": "xingchen-plus-v2",
// 数字人音频播放采样率
"outboundSampleRate": 48000,
// 是否开启RTC内置的AEC,默认开启
"useRtcAec": true,
// 用户ID,不做权限校验,保证唯一性即可,建议使用UUID传入
"userId": "lxx",
// 音色Id,必传
"voiceId": "longxiaochun"
},
"requestConfig": {
// Header中预置鉴权信息
"headers": {
// 'Bearer ' + '在此处填入ApiKey'
"Authorization": "鉴权信息,通过“星尘-我的空间-密钥管理”获取",
"x-fag-appcode": "aca",
"x-fag-servicename": "aca-videochat-init"
},
// 星尘网关的地址
"url": "https://nlp.aliyuncs.com/v2/api/videochat/initialize"
}
start
初始化成功后,启动对话流程
/**
* 初始化成功后,启动对话流程
* @param chatCallback 主回调,除了初始化过程的所有消息,都会从这里透出给上层
*/
fun start(chatCallback: IChatCallback)
参数名称 | 类型 | 是否必须 | 描述 |
chatCallback | IChatCallback | 是 | 活动实例 |
其中IChatCallback为主回调,除了初始化接口,所有消息都会从这里透出给上层,详细接口为
onStartResult
对话启动结果,鉴权、客户端加入通道成功后,会回调该消息
/**
* 对话启动结果,鉴权、客户端加入通道成功后,会回调该消息
*/
fun onStartResult(isSuccess: Boolean, errorInfo: TYError?)
其中TYError的格式为
参数名称 | 类型 | 是否必须 | 描述 |
key | Int | 是 | 错误信息Key |
message | String | 否 | 错误信息Message |
onReadyToSpeech
对话准备完成,三端(客户端/VoiceChat/Avatar)均加入通道后,会回调该消息,此时才能调用业务接口
/**
* 对话准备完成,三端(客户端/VoiceChat/Avatar)均加入通道后,会回调该消息,此时才能调用业务接口
*/
fun onReadyToSpeech()
onGotRenderView
RTC准备好的渲染组件,需要调用者把它显示到屏幕上
/**
* RTC准备好的渲染组件,需要调用者把它显示到屏幕上
*/
fun onGotRenderView(renderView: SurfaceView)
onInterruptResult
主动打断的回调,包括手动打断和语音打断
/**
* 主动打断的回调,包括手动打断和语音打断
*/
fun onInterruptResult(isSuccess: Boolean, errorInfo: TYError?)
参数名称 | 类型 | 是否必须 | 描述 |
isSuccess | Boolean | 是 | True or False |
errorInfo | TYError | 否 | 错误信息,若接口成功,该项可能为空 |
onStateChanged
数字人状态切换
/**
* 状态切换
*/
fun onStateChanged(state: DialogState)
其中DialogState为数字人状态,详细信息如下
public static enum DialogState {
DIALOG_IDLE(0),// IDLE状态
DIALOG_LISTENING(1),// 数字人在听
DIALOG_RESPONDING(2),// 数字人在说
DIALOG_THINKING(3);// 数字人在想
}
onVolumeChanged
音频强度回调
/**
* 音量强度回调
* @param audioType 参考 {@link Constant.TYVolumeSourceType}
* @param audioLevel 0-100
*/
fun onVolumeChanged(audioLevel: Float, audioType: Constant.TYVolumeSourceType)
参数名称 | 类型 | 是否必须 | 描述 |
audioLevel | Float | 是 | 音频强度,归一到【0,1】区间 |
audioType | TYVolumeSourceType | 是 | 音频类型 |
其中TYVolumeSourceType为枚举类型,详细信息如下
/**
* 语音类型,分为本地采集和远端TTS两种
*/
enum class TYVolumeSourceType {
MIC, // 本地采集
PLAYER // 远端TTS
}
onMessageReceived
对话过程中的文本详情回调
/**
* 对话的文本详情回调
* @param chatMessage
*/
fun onMessageReceived(chatMessage: TYVoiceChatMessage)
其中TYVoiceChatMessage为文本详情封装类,详细信息如下
参数名称 | 类型 | 是否必须 | 描述 |
chatMessageType | ChatMessageType | 是 | 消息类型 |
chatMessageText | String | 是 | 消息文本 |
isFinish | Boolean | 是 | 是否结束,用户说/AI说每次会返回当前已识别到的全部内容,说完后,该标志位为true |
其中ChatMessageType为枚举类型,详细信息如下
/**
* 消息类型,分为用户说/AI说两种
*/
enum class ChatMessageType {
SPEAKING, // 用户问
RESPONDING // AI回答
}
onErrorReceived
对话过程中的异常回调
/**
* 对话过程中的异常信息
* @param errorInfo 异常信息
*/
fun onErrorReceived(errorInfo: TYError)
interrupt
打断数字人说话,异步方法,打断结果会通过回调返回
/**
* 打断数字人说话
*/
fun interrupt()
startSpeech
Push2Talk模式下,用户开始说话
/**
* Push2Talk 用户开始说话
*/
fun startSpeech()
stopSpeech
Push2Talk模式下,用户说话完成
/**
* Push2Talk 用户结束说话
*/
fun stopSpeech()
cancelSpeech
Push2Talk模式下,用户取消说话
/**
* Push2Talk 用户取消说话
*/
fun cancelSpeech()
muteLocalMic
是否关闭本地麦克风采集
/**
* 是否关闭本地麦克风采集
*/
fun muteLocalMic(mute: Boolean): Boolean
requestToRespond
请求服务端回答指定问题or做TTS播放出来
/**
* 请求服务端回答指定问题or做TTS播放出来
* @param type: transcript 表示直接把文本转语音,prompt 表示把文本送大模型回答
* @param text:对应的文本
*/
fun requestToRespond(type: String, text: String)
exit
退出SDK,退出页面时必须调用该方法,否则会导致实例未释放,功能会出现异常
/**
* 销毁实例
*/
fun exit()
附录
错误码
网关服务错误
云端渲染、端测渲染(端到端)数字人错误码
错误码 | 错误名称 | 错误说明 | 解决方案 |
400 | aca.error.invalid.param | 初始化参数错误,参考返回的错误信息 | 重新在星尘官网确认相关参数 |
401 | 用户未认证 | ApiKey错误 | 1、在星尘官网上确认自己的apiKey是否正确 2、确认SDK初始化的ApiKey有没有加'Bearer ' |
465 | aca.error.not.paas.whitelist | 没有开通白名单 | 联系邮箱tongyixingchen@service.aliyun.com |
403 | aca.error.avatar.permission.error | 没有形象的使用权限 | 请确认账号是否拥有形象使用权限 |
403 | aca.error.voice.permission.error | 没有声音的使用权限 | 请确认账号是否拥有声音使用权限 |
422 | aca.error.videochat.initialize.limit | 数字人资源不足 | 请联系产品运营同学进行错误排查 |
431 | aca.error.videochat.quota.exceeded | 超过运行状态数限制 | 同一个账号同时开启的会话有数量限制,需要更多请联系产品运营同学 |
500 | aca.error.internal.exception | 内部服务错误 | 请联系产品运营同学进行错误排查 |
501 | aca.error.gateway.exception | 服务端验证ApiKey失败 | 1、在星尘官网上确认自己的ApiKey是否正确 2、确认SDK初始化的ApiKey有没有加 'Bearer ' |
RTC错误
错误码 | 错误说明 | 是否断连 | 解决方案 |
1000 | RTC初始化参数错误 | 是 | 检查SDK内部调用星尘initialize初始化的接口返回 |
1001 | RTC鉴权失败 | 是 | 检查SDK内部调用星尘initialize初始化的接口返回 |
语音服务错误
错误码 | 错误说明 | 是否断连 | 解决方案 |
40000000 | 客户端错误 | 是 | 数字人执行退出操作,重新初始化数字人实例 |
40000001 | 参数不合规、检查参数 | ||
40000002 | 指令不支持,如指令名称错误 | ||
40000003 | 指令不合规,如指令格式错误 | ||
40000004 | 连接错误 | ||
40010000 | 拒绝访问 | ||
40010001 | 未授权 | ||
40020000 | 语音输入或输出违规 | 否 | 继续对话 |
40030000 | 对话静默超时 | 是 | 数字人执行退出操作,重新初始化数字人实例 |
50000000 | 服务内部错误 | ||
50000001 | 服务内部错误 | ||
50010000 | 语音识别内部错误 | 否 | 继续对话 |
50020000 | 大模型内部错误 | ||
50030000 | 语音合成内部错误 | ||
50040000 | 数字人内部错误 | 是 | 数字人执行退出操作,重新初始化数字人实例 |
50040001 | 数字人初始化失败 | ||
50040002 | 数字人初始化超时 |
兼容性
本SDK最低支持Android 8.0机器,即minSdk 26