万相数字人开放平台推出的适用于iOS数字人流媒体服务SDK。当您调用服务端OpenAPI CreateChatSession - 创建实时数字人会话接口获取RTC入会信息后,可以在iOS搭建App,实现数字人拉流和实时对话。VideoChatiOSSdk通过SDK下载/集成(AliRTC)提供视频流的订阅,并通过RTC内置的消息通道进行信令传输
产品能力
云端渲染-音频驱动数字人是通过阿里云RTC提供鉴权通道,SDK支持通过外部传入音频,完成数字人的口型推理、面部驱动、渲染等全流程
云端渲染-音频驱动数字人不具备完整的语音交互,仅支持调用侧传入音频进行驱动,支持在数字人播报时进行打断
接入前须知
SDK不包含操作服务端实例的接口(如数字人初始化),如有需要请参考OpenAPI文档;
Demo 需要依赖配合后端应用才能体验,请先确认建立好可以调用OpenAPI的后端应用。
使用限制:
系统版本:支持iOS 14及以上版本
其他限制,可参考SDK下载/集成
若使用本文档提供的SDK,用于对公众提供人工智能生成合成服务,作为服务提供者需遵守《互联网信息服务深度合成管理规定》《人工智能生成合成内容标识办法》以及相关标准要求,履行人工智能生成合成内容标识的义务。
接入方法
下载示例工程及SDK Framework
从OSS上下载VideoChatSdkDemo_V0_2_0,并进行解压
环境配置
Xcode 14及以上
加载SDK和依赖
xcode中导入如下的framework,可从示例工程中获取
// 数字人SDK
digital_human_ios_sdk.framework
// RTC SDK
AliVCSDK_ARTC.framework
alivcffmpeg.framework
queen.framework
// 视频解码相关SDK
ffmpegkit.framework
libavcodec.framework
libavdevice.framework
libavfilter.framework
libavformat.framework
libavutil.framework
libswresample.framework
libswscale.framework
// Zip SDK
ZIPFoundation.framework权限相关
SDK和数字人交互需要用到录音权限,在Info.plist文件中增加如下代码:
<key>NSMicrophoneUsageDescription</key> <string>{使用麦克风的原因描述}</string>
Flutter接入方式
本SDK暂未提供Flutter原生版本,可以将Flutter作为module集成在项目中,通过MethodChannel实现两端的相互调用,可参考Flutter接入移动解析HTTPDNS Android/iOS SDK实践方案,线上已有客户基于该方案完成SDK的接入和App的上线
接口列表
API | 功能描述 |
init | 初始化方法,主要用来配置参数 |
start | 初始化成功后,启动对话流程 |
interrupt | 打断数字人说话 |
pushAudioData | 外部传入音频,驱动数字人,V0.1.3版本开始支持 |
exit | 退出 |
扩展接口 | SDK针对音频采集和播放提供了一些自定义配置 |
接口详情
初始化SDK
init
/**
* 初始化方法,主要用来配置参数,用于云渲染
* @param license 扩展字段,云渲染暂未用到
* @param avatarInitData 用户从平台拿到的数字人和资产信息
* @param dialogConfig 业务层对话配置,如Tap2Talk/PushTalk/Duplex等
*/
init(license: String, avatarInitData: TYAvatarInitData, dialogConfig: TYDialogConfig)参数说明
参数名称 | 类型 | 是否必传 | 描述 |
avatarInitData | TYAvatarInitData | 是 | 数字人初始化数据 |
dialogConfig | TYDialogConfig | 是 | 数字人对话模式配置 |
其中TYAvatarInitData为数字人初始化数据,主要包括RTC入会信息和资产信息
TYAvatarInitData数据可通过调用服务端OpenAPI CreateChatSession - 创建实时数字人会话接口获取,请务必在使用前验证服务端OpenAPI接口是否能正常调用
获取成功后,将Data字段对应的JsonObject传入SDK即可
"data": {
"sessionId": "9827f4bd-5008-4d34-98fb-62598f3ad3b5",
"rtcParams": {
"appId": "xxx",
"avatarUserId": "xxx",
"channel": "channel_info",
"clientUserId": "xxx",
"gslb": "https://gw.rtn.aliyuncs.com",
"nonce": "f8b0ef02c5da778f4488e2470c",
"serverUserId": "xxx",
"timestamp": 1560588594,
"token": "xxx"
}
}参数名称 | 类型 | 是否必传 | 描述 |
rtcParams | TYAvatarInitConfig | 是 | RTC入会信息 |
sessionId | String? | 否 | 本轮对话的全局sessionId |
TYAvatarInitConfig为RTC入会信息
参数名称 | 类型 | 是否必传 | 描述 |
appId | String | 是 | RTC应用id |
channel | String | 是 | RTC通道信息 |
gslb | String | 是 | RTC负载均衡地址 |
timestamp | long | 是 | RTC鉴权有效的时间戳 |
token | String | 是 | RTC鉴权相关的token |
clientUserId | String | 是 | 客户端入会的id |
serverUserId | String | 是 | 服务端入会的id |
avatarUserId | String | 是 | 数字人入会的id |
nonce | String | 否 | 鉴权标识 |
sessionId | String | 是 | 数字人对话的全局sessionId |
TYDialogConfig为对话属性配置信息
参数名称 | 类型 | 是否必传 | 描述 |
renderType | TYAvatarRenderType | 是 | 渲染类型,云渲染-音频驱动模式为remote_avatar_only |
mode | TYVoiceChatMode | 是 | 对话模式,当前仅支持Tap2Talk |
keepAlive | Boolean | 否 | 是否开启心跳保活,默认开启 |
keepAlivePeriod | Int | 否 | 心跳保活间隔,默认10s |
outboundSampleRate | Int | 否 | TTS音频播放采样率,默认48000 |
TYAvatarRenderType为渲染类型信息,可参考
/**
* 数字人渲染类型
*/
object TYAvatarRenderType {
const val REMOTE_RENDER_AVATAR = "cloud" // 云渲染-全链路
const val REMOTE_RENDER_AVATAR_ONLY = "remote_avatar_only" // 云渲染-音频驱动
const val LOCAL_RENDER_AVATAR = "local" // 端渲染-全链路
const val LOCAL_RENDER_AVATAR_ONLY = "avatar_only" // 端渲染-音频驱动
}TYVoiceChatMode为对话模式,可参考
/**
* 会话模式
*/
object TYVoiceChatMode {
const val TAP2TALK = "tap2talk" // 默认方式,一方说完,另一方可以说话
const val PUSH2TALK = "push2talk" // 用户主动开始和结束说话
const val DUPLEX = "duplex" // 全双工模式,可语音打断
}开启对话
start
初始化完成后,启动对话流程
/**
* 启动对话流程
*
* @param chatCallback 主回调,SDK运行过程中的所有信息,都会从这里透出给上层
*/
func start(completion: @escaping (Bool, TYError?) -> Void)参数名称 | 类型 | 是否必传 | 描述 |
completion | @escaping (Bool, TYError?) | 是 | 启动对话的回调 |
TYError的格式为
参数名称 | 类型 | 是否必传 | 描述 |
key | Int | 是 | 错误信息Key |
message | String | 否 | 错误信息Message |
绑定回调
并不是所有回调都需要绑定,建议开发者根据业务开发需求进行绑定即可。
onReadyToSpeech: 对话准备完成,三端(客户端/VoiceChat/Avatar)均加入通道后,会回调该消息,此时才能调用业务接口
/** * 对话准备完成,三端(客户端/VoiceChat/Avatar)均加入通道后,会回调该消息,此时才能调用业务接口 */ public var onReadyToSpeech: (() -> Void)?
onFirstFrameReceived: 收到第一帧视频帧
/** * RTC收到第一帧视频 */ public var onFirstFrameReceived: (() -> Void)?
onStateChanged: 数字人状态切换
/** * 状态切换 */ public var onStateChanged: ((TYVoiceChatState) -> Void)?TYVoiceChatState为数字人状态,详细信息如下
/// VoiceChat对话状态,和服务端状态一一对应 public enum TYVoiceChatState: String { case idle = "Idle" // 空置状态,未连接/连接断开对应的状态 case listening = "Listening" // 听 case responding = "Responding" // 说 case thinking = "Thinking" // 思考 }
onVolumeChanged: 音频强度回调
/** * 音量强度回调 * @param audioType 音频类型参考 * @param audioLevel 音频强度,归一到【0,1】区间 */ public var onVolumeChanged: ((Float, TYVolumeSourceType) -> Void)?TYVolumeSourceType为音频类型,详细信息如下
/** * 语音类型,分为本地采集和远端TTS两种 */ public enum TYVolumeSourceType: Int { case mic case player }
onPerformanceInfoTrack:对话过程中的性能监测
/** * 对话过程中的性能监测 * @param TYChatPerformace 信息详情 */ public var onPerformaceDataReceived: ((TYChatPerformace) -> Void)?TYChatPerformace为性能信息详情,具体如下
参数名称
类型
是否必传
描述
llmDelay
Int64
是
llm的时延
ttsDelay
Int64
是
tts的时延
avatarDelay
Int64
是
数字人画面帧的时延
totalDelay
Int64
是
当前roundCount对话的总时延
roundCount
Int64
是
会话轮次的计数值
roundAverageTotalDelay
Int64
是
当前roundId对话的平均总时延,即totalDelay的平均值
onErrorReceived: 对话过程中的异常回调
/** * 对话过程中的异常信息 * @param errorInfo 异常信息 */ public var onErrorReceived: ((TYError) -> Void)?
打断
interrupt
打断数字人说话,异步方法,打断结果会通过回调返回
/**
* 打断数字人说话
*/
func interrupt()推送音频数据
pushAudioData
调用侧传入音频数据给SDK,驱动数字人
/**
* 推送音频数据,该接口仅在单独数字人模式下生效
* @param audio 音频数据
* @param end 是否结束,音频支持流式推送,最后一帧end需设置为true
* @return 推送结果
*/
public func pushAudioData(_ audio:[Int16], end: Bool) ->Bool?退出
exit
退出SDK,退出页面时必须调用该方法,否则会导致实例未释放,功能会出现异常
/**
* 销毁实例
*/
fun exit()扩展接口
用户在一些场景下,需要对音频采集和播放做一些自定义配置,此处开放一些配置参数,通过调用getRtcConfig()获取TYRtcConfig对象,当前支持的配置参数如下。注意:该接口需要在SDK start接口前调用生效
参数名称 | 类型 | 默认值 | 描述 |
playOutAudioVolume | Integer | 100 | TTS音频增益,值域为[0, 400],大于100标识增大音量,小于100标识降低音量 |
recordAudioVolumeBeforeVAD | Integer | 100 | VAD唤起前采集音量大小,值域为[0, 400],大于100标识增大音量,小于100标识降低音量。双工对话模式建议设置为40,其他对话模式建议设置为100 |
recordAudioVolumeAfterVAD | Integer | 100 | VAD唤起后采集音量大小,值域为[0, 400],大于100标识增大音量,小于100标识降低音量 |
renderMode | AliRtcEngine.AliRtcRenderMode | AliRtcRenderMode.AliRtcRenderModeAuto | 视频流渲染的填充模式,AliRtcRenderModeAuto(0):自动模式 AliRtcRenderModeStretch(1):拉伸平铺模式 AliRtcRenderModeFill(2):填充黑边模式 AliRtcRenderModeClip(3):裁剪模式 |
错误码
应用内部错误
错误码 | 错误说明 | 解决方案 |
1120 | RTC参数过期 场景1)生成RTC的json信息存在有效期限制,拿到信息后超出5min未入会; 场景2)同样的RTC参数重复入会 | 刷新RTC入会参数 |
RTC错误
错误码 | 错误说明 | 解决方案 |
1000 | RTC初始化参数错误 | 检查RTC入会信息 |
1001 | RTC鉴权失败 | 检查RTC入会信息 |
1002 | RTC加入频道错误 | 检查网络或者RTC入会信息 |
1003 | RTC数据丢包 | 请联系产品运营同学进行错误排查 |
1004 | RTC 数据通道崩溃 | 请联系产品运营同学进行错误排查 |
1005 | RTC房间被销毁 | RTC房间被服务端主动销毁 |
1006 | 用户被踢出RTC房间 | 服务端将用户主动踢出房间 |
1007 | 端渲染模式下语音LAG | 请联系产品运营同学进行错误排查 |
服务端错误
参考服务端错误码