数字人流媒体服务WebSDK
aliyun-avatar-sdk,数字人开放平台推出的适用于Web浏览器的数字人流媒体服务SDK。当您调用服务端OpenAPI StartInstance接口获取RTC和IM参数信息后,可以在Web端搭建本地SDK,实现数字人拉流和双工对话。aliyun-avatar-sdk通过阿里云音视频通信服务(阿里云RTC)提供视频流的订阅,并通过标准WebSocket与服务端建立IM连接。
接入前须知
aliyun-avatar-sdk不包含操作服务端实例的接口(如启动数字人、结束数字人、播报文本等功能),如有需要请参考OpenAPI文档;
页面域名请使用HTTPS,否则在部分机型上会出现录音权限被拒绝,拉流播放失败等问题;
由于网络等原因导致im连接中断(错误码:15011002)时,连接断开期间本地录音将不会保留;
各平台浏览器兼容性测试详见文末附录各平台浏览器兼容性;
由于chrome对自动播放的限制,禁止自动播放音频,如果您的页面在没有任何用户点击的情况下自动拉流(例如用js触发的方式自动拉流),会出现数字人无声音的问题,这种情况有三个解决方案,推荐程度依次降低:
建议您添加按钮来触发拉流;
或建议您在实例化SDK时开启静音订阅(参考是否静音订阅流),并在UI上设置音量开关按钮,提醒用户打开声音;
(aliyun-avatar-sdk的兜底策略)如您不采用以上两种方案,则需要用户点击页面任意位置解除声音播放限制;
接入方法
在线安装
可以通过npm安装
$ # save into package.json dependencies with -S
$ npm install aliyun-avatar-sdk -S
离线安装
从OSS下载SDK包
$ # 切换到项目根目录
$ cd your-project
$ # 解压下载的压缩包
$ tar -xvf avatar-sdk.tar.gz
$ # 本地安装
$ npm install avatar-sdk
SDK使用文档
类名 | 适用的数字人类型 | 包含功能 |
DialogAvatarSDK | 互动数字人 | rtc拉流、im连接、本地录音 |
BroadcastingAvatarSDK | 播报数字人、推流数字人 | rtc拉流 |
互动数字人 - DialogAvatarSDK
快速入门
/*
* 引入DialogAvatarSDK
*/
import { DialogAvatarSDK } from 'aliyun-avatar-sdk';
/*
* 获取建立im和拉rtc流的关键信息
*/
// StartInstanceRes:从服务端StartInstance接口返回值
const { requestId, sessionId, token, channel } = StartInstanceRes;
/*
* 调用构造方法,输入服务端返回的信息
*/
const dialogAvatarSDK = new DialogAvatarSDK({
// im连接参数
tenantId: '', // 用户自行提供
appId: '', // 用户自行提供
sessionId,
token, // 注意是StartInstance外层返回的token,不是channel里的token
// rtc拉流相关参数
/*
* 注意StartInstance接口返回的channel中的变量为大驼峰,如果服务端没有转化的话
* 前端需要在这里手动转成小驼峰
*/
channel:{
appId: channel.AppId, // 手动转成小驼峰
channelId: channel.ChannelId,
expiredTime: channel.ExpiredTime,
gslb: channel.Gslb,
nonce: channel.Nonce,
token: channel.Token,
type: channel.Type,
userId: channel.UserId
},
// 用来播放rtc下行流的容器
videoDOM: document.getElementById('rtc'),
// 选项
options: {
wsUrl: '', // 建立IM连接的websocket地址
maxReconnectTimeout: 300000, // 断线重连最大尝试时间(ms),超出这个时间仍未重连成功将抛出断线重连超时错误
audio: {
autoStartRecord: false, // 是否在初始化过程中自动开启浏览器录音
interval: 100, // 音频采集间隔(ms),注意不能小于60ms,不能大于1000ms,否则会抛出错误,音频单通道16K 16bit
autoDodge: false, // 是否开启音频闪避
},
rtc: {
muted: false, // 是否静音订阅流
},
},
// 初始化成功回调
onInitSuccess: () => {
console.log('IM连接成功,RTC拉流成功');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
},
// RTC初始化成功回调
onRtcInitSuccess: () => {
console.log('RTC拉流成功,等待IM链接...');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
},
// IM初始化成功回调
onIMInitSuccess: () => {
console.log('IM连接成功,等待RTC拉流...');
},
// 错误回调
onError: (e) => {
console.error(e);
},
// 收音开始回调
onRecordingStart: () => {
// 可以在ui上提示用户
},
// 收音结束回调
onRecordingStop: () => {
// 可以在ui上提示用户
},
// ASR下发文本回调
onASR: (text, sentenceId) => {
console.log(`Answer: ${text}`);
console.log(`sentenceId: ${sentenceId}`);
},
// 数字人回答下发文本回调
onAnswer: (text, sentenceId) => {
console.log(`Answer: ${text}`);
console.log(`sentenceId: ${sentenceId}`);
},
// 未知im消息回调,用于接收后端业务增加新的消息类型
onUnknownIMMessage: (msg) => {
console.log(msg);
},
});
/*
* 初始化
*/
dialogAvatarSDK
.init()
.then(() => {
// 等同于onInitSuccess
console.log('IM连接成功,RTC拉流成功');
})
.catch((e) => {
// 同样的错误也会被onError捕获
console.log(e);
});
dialogAvatarSDK.openAutoDodge(); // 开启音频闪避
dialogAvatarSDK.stopRecording(); // 手动停止收音/自定义音频采集,会触发onRecordingStop
dialogAvatarSDK.startRecording().then(()=>{
// 手动开启收音/自定义音频采集,会触发onRecordingStart
console.log('录音成功');
});
dialogAvatarSDK.destroy(); // 销毁实例
新建实例
构造函数入参如下表:
参数名称 | 描述 | 是否必选 | 类型 | 默认值 | 备注 |
tenantId | 用户自行提供租户id | 是 | string | ||
appId | 用户自行提供应用id | 是 | string | ||
sessionId | StartInstance返回的会话id | 是 | string | ||
token | im对话的token,注意是OpenAPI StartInstance外层返回的token,不是channel里的token | 是 | string | 没有token无法建立im对话连接 | |
channel | 用来rtc拉流的信息,OpenAPI StartInstance返回的channel字段 | 是 | object | 注意StartInstance接口返回的channel中的变量为大驼峰,需要您手动转化成小驼峰命名 | |
videoDOM | 用来播放rtc下行流的容器 | 是 | HTMLVideoElement | ||
options | 用户自定义配置 | 否 | object | ||
options.wsUrl | 建立IM连接的Websocket地址 | 否 | string | wss://avatar-im.console.aliyun.com/ws | |
options.maxReconnectTimeout | 断线重连最大尝试时间(ms),超出这个时间仍未重连成功将抛出断线重连超时错误 | 否 | number | 300000 | |
options.rtc.muted | 是否静音订阅流 | 否 | boolean | false | |
options.audio.autoStartRecord | 是否在初始化过程中自动开启浏览器录音 | 否 | boolean | false | |
options.audio.interval | 音频采集间隔,单位毫秒 | 否 | number | 100 | 注意不能小于60ms,不能大于1000ms,否则会抛出错误 |
options.audio.autoDodge | 是否开启音频闪避 | 否 | boolean | false | 音频闪避:当RTC视频流数字人说话时,自动暂停浏览器录音 |
onInitSuccess | 初始化成功回调 | 否 | function | 表示RTC和IM通道初始化均完成,在onIMInitSuccess和onRtcInitSuccess之后触发 | |
onIMInitSuccess | IM初始化成功回调 | 否 | function | ||
onRtcInitSuccess | RTC初始化成功回调 | 否 | function | ||
onError | 错误回调 | 否 | function | ||
onASR | asr识别文本回调 | 否 | function | ||
onAnswer | 数字人回答文本回调 | 否 | function | ||
onRecordingStart | 收音开始回调 | 否 | function | ||
onRecordingStop | 收音结束回调 | 否 | function | ||
onUnknownIMMessage | 未知的im消息,用于接收后续业务增加新的消息类型 | 否 | function |
绑定回调
除了在构造函数绑定监听回调外,还可以直接在实例上绑定监听回调;
建议在初始化操作init()执行前绑定监听回调,否则可能会出现回调没有被触发的情况。
onInitSuccess 初始化成功回调
表示RTC和IM通道初始化均完成,可以与数字人正常进行对话,在onIMInitSuccess和onRtcInitSuccess之后触发
dialogAvatarSDK.onInitSuccess = () => {
console.log('IM连接成功,RTC拉流成功');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
};
onIMInitSuccess IM初始化成功回调
dialogAvatarSDK.onIMInitSuccess = () => {
console.log('IM连接成功,等待RTC拉流...');
};
onRtcInitSuccess RTC初始化成功回调
dialogAvatarSDK.onRtcInitSuccess = () => {
console.log('RTC拉流成功,等待IM链接...');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
};
onError 错误回调
dialogAvatarSDK.onError: (e) => {
console.error(`errorCode: ${e.errorCode}, source:${e.source}, errorMsg:${e.errorMsg}`);
}
回调入参e数据结构:
参数名称 | 描述 | 类型 |
errorCode | 错误码,详情参考文末错误码表 | number |
source | 错误来源(AliRtc和Avatar,前者代表来自阿里云RTC的错误,后者代表来自数字人或客户端的错误) | string |
errorMsg | 错误描述 | string |
onASR ASR下发文本回调
dialogAvatarSDK.onASR = (text, sentenceId) => {
console.log(`ASR Result: ${text}`);
console.log(`sentenceId: ${sentenceId}`);
};
回调入参说明:
参数名称 | 描述 | 类型 |
text | asr识别文本 | string |
sentenceId | 句子id | string |
onAnswer 数字人回答下发文本回调
dialogAvatarSDK.onAnswer = (text, sentenceId) => {
console.log(`Answer: ${text}`);
console.log(`sentenceId: ${sentenceId}`);
};
回调入参说明:
参数名称 | 描述 | 类型 |
text | 数字人回答文本 | string |
sentenceId | 句子id | string |
onRecordingStart 收音开始回调
dialogAvatarSDK.onRecordingStart = () => {
// 可以在ui上提示用户开始收音
};
onRecordingStop 收音结束回调
dialogAvatarSDK.onRecordingStop = () => {
// 可以在ui上提示用户停止收音
};
初始化
初始核心流程:
建立im连接;
rtc拉流;
开启浏览器录音并通过im发送;(当options.autoStartRecord为true时)
init 初始化回调
dialogAvatarSDK.init().then(
() => {
// 等同于onInitSuccess
console.log('IM连接成功,rtc拉流成功');
}
).catch(
(e) => {
// 该错误也会被onError捕获
console.error(e);
}
)
暂停/开始收音
dialogAvatarSDK.stopRecording(); // 手动停止收音/自定义音频采集,会触发onRecordingStop
dialogAvatarSDK.startRecording().then(()=>{
// 手动开启收音/自定义音频采集,会触发onRecordingStart
console.log('录音成功');
});
RTC静音/取消静音
dialogAvatarSDK.muteRtc();
dialogAvatarSDK.unMuteRtc();
高级功能
暴露阿里云RTC原始对象
// 访问aliyun-webrtc 原始对象
console.log(dialogAvatarSDK.rtc.aliRtcEngine);
暴露Websocket原始对象
// 访问WebSocket 原始对象
console.log(dialogAvatarSDK.websocket);
音频闪避
自动检测RTC视频流数字人说话暂停收音,有两种开启方式:
自动开启:
如果构造函数的options.audio.autoDodge字段设置为true,则会自动开启
手动开启:
/*
* 执行构造函数后,手动开启/关闭音频闪避
*/
dialogAvatarSDK.openAutoDodge();
dialogAvatarSDK.closeAutoDodge();
销毁实例
断开rtc拉流、im连接、停止录音,避免资源浪费;
dialogAvatarSDK.destroy();
该方法仅仅销毁客户端实例,若要避免云端资源浪费,请调用OpenAPI StopInstance接口
播报数字人 - BroadcastingAvatarSDK
快速入门
/*
* 获取建立im和拉rtc流的关键信息
*/
// StartInstanceRes:从服务端StartInstance接口返回值
const { requestId, channel } = StartInstanceRes;
/*
* 调用构造方法,输入服务端返回的信息
*/
const broadcastingAvatarSDK = new BroadcastingAvatarSDK({
// rtc拉流相关参数
/*
* 注意StartInstance接口返回的channel中的变量为大驼峰,如果服务端没有转化的话
* 前端需要在这里手动转成小驼峰
*/
channel:{
appId: channel.AppId, // 手动转成小驼峰
channelId: channel.ChannelId,
expiredTime: channel.ExpiredTime,
gslb: channel.Gslb,
nonce: channel.Nonce,
token: channel.Token,
type: channel.Type,
userId: channel.UserId
},
// 用来播放rtc下行流的容器
videoDOM: document.getElementById('rtc'),
options: {
maxReconnectTimeout: 300000, // 断线重连最大尝试时间(ms),超出这个时间仍未重连成功将抛出断线重连超时错误
rtc: {
muted: false, // 是否静音订阅流
},
},
// 初始化成功回调
onInitSuccess: () => {
console.log('RTC拉流成功');
},
// 错误回调
onError: (e) => {
console.error(e);
},
});
/*
* 初始化
*/
broadcastingAvatarSDK
.init()
.then(() => {
// 等同于onInitSuccess
console.log('RTC拉流成功');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
})
.catch((e) => {
// 同样的错误也会被onError捕获
console.log(e);
});
broadcastingAvatarSDK.destroy(); // 销毁实例
新建实例
构造函数入参
参数名称 | 描述 | 是否必选 | 类型 | 默认值 | 备注 |
channel | 用来rtc拉流的信息,OpenAPI StartInstance返回的channel字段 | 是 | object | 注意StartInstance接口返回的channel中的变量为大驼峰,需要您手动转化成小驼峰命名 | |
videoDOM | 用来播放rtc下行流的容器 | 是 | HTMLVideoElement | ||
options | 用户自定义配置 | 否 | object | ||
options.rtc.muted | 是否静音订阅流 | 否 | boolean | false | |
options.maxReconnectTimeout | 断线重连最大尝试时间,超出这个时间仍未重连成功将抛出断线重连超时错误, 单位毫秒 | 否 | number | 300000 | |
options.onInitSuccess | 初始化成功回调 | 否 | function | ||
onError | 错误回调 | 否 | function |
绑定回调
除了在构造函数绑定监听回调外,还可以直接在实例上绑定监听回调;
建议在初始化操作init()执行前绑定监听回调,否则可能会出现回调没有被触发的情况。
onInitSuccess 初始化成功回调
broadcastingAvatarSDK.onInitSuccess = () => {
console.log('RTC拉流成功');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
};
onError 错误回调
broadcastingAvatarSDK.onError: (e) => {
console.error(`errorCode: ${e.errorCode}, source:${e.source}, errorMsg:${e.errorMsg}`);
}
回调入参e数据结构:
参数名称 | 描述 | 类型 |
errorCode | 错误码 | number |
source | 错误来源(AliRtc和Avatar,前者代表来自阿里云RTC的错误,后者代表来自数字人或客户端的错误) | string |
errorMsg | 错误描述 | string |
初始化
初始化核心流程:rtc拉流
broadcastingAvatarSDK.init().then(
() => {
// 等同于onInitSuccess
console.log('RTC拉流成功');
console.log(dialogAvatarSDK.rtc.aliRtcEngine); // 此时可以访问aliRtcEngine原始对象
}
).catch(
(e) => {
// 该错误也会被onError捕获
console.error(e);
}
)
RTC静音/取消静音
broadcastingAvatarSDK.muteRtc();
broadcastingAvatarSDK.unMuteRtc();
高级功能
暴露阿里云RTC原始对象
console.log(broadcastingAvatarSDK.rtc.aliRtcEngine); // 访问aliyun-webrtc 原始对象
销毁实例
断开rtc拉流,避免资源浪费;
该方法仅仅销毁客户端实例,若要避免云端资源浪费,请调用OpenAPI StopInstance接口
broadcastingAvatarSDK.destroy();
附录
错误码表
AliRtc 音视频服务错误
触发onError回调时,source字段为"AliRtc"时,标志为阿里云RTC错误,详见
数字人服务错误
触发onError回调时,source字段为"Avatar"时,标志为数字人服务/本地客户端错误,详见下表
错误码 | 错误消息 | 描述 | 解决方案 |
50009999 | 系统内部错误 | 系统内部错误 | 内部未明确错误,需要通过日志文件寻求支持 |
50000001 | 缺少必填参数:audio | 缺少必填参数 | 请确认接口调用是的必须参数 |
50000002 | 非法参数:audio | 非法参数 | 请确认参数格式是否错误或者缺少必须字段 |
50000006 | 无效的sessionId | 无效的sessionId | session失效或者sessionid传参错误 |
50010001 | 发送的音频大小超过限制 | 发送的音频大小超过限制(默认最大为1s的PCM音频) | 查看采集发送的音频大小,减小采集音频的时长 |
50010002 | 互动数字人相关必要配置缺失 | 互动数字人相关必要配置缺失 | 请检查开发平台对应业务的互动机器人配置(主要为机器人的id\ak\sk) |
50010003 | 互动机器人问答结果为空 | 互动机器人问答结果为空 | |
50010004 | 天气预报机器人请求次数已达上限 | 天气预报机器人请求次数已达上限 | 请更换自己购买的云小蜜机器人对应配置 |
50020001 | ASR处理未知异常 | ASR处理未知异常 | |
50020002 | ASR长时间未收到对应的正确格式音频 | ASR长时间未收到对应的正确格式音频 | 检查是否在持续采集上行的音频或者音频的内容格式是否正确 |
50040001 | 云小蜜给出的errcode:errMsg | 无权限访问对应云小蜜资源 | 检查对应云小蜜账号的权限 |
50040002 | 云小蜜给出的errcode:errMsg | 配置的云小蜜账号已被冻结 | 检查云小蜜对应账号是否已经欠费 |
50040004 | 云小蜜给出的errcode:errMsg | 云小蜜对话未知异常 | |
15011000 | 服务端双工对话开启失败 | IM通道建立后,初始化对话通道失败 | |
15011001 | IM通道异常 | 可能的原因:
|
|
15011002 | IM断线 | IM因网络问题断开连接 | 请检查网络连接,在最大重连时间options.maxReconnectTimeout内恢复网络连接会自动重连 |
15011003 | IM重连超时 | IM断线后超出最大重连时间仍未重连成功 | 请销毁当前实例,重新新建实例 |
15021000 | rtc频道关闭 | 可能的原因:相同实例在另一个端登录; | 请销毁当前实例,重新新建实例 |
15021001 | rtc重连超时 | rtc断线后超出最大重连时间仍未重连成功 | 请销毁当前实例,重新新建实例 |
15031002 | 未获取到录音权限 | 请检查麦克风设备是否正常运算,或者浏览器麦克风权限是否做了限制 |
|
15031003 | video参数不能为空 | rtc拉流前应提供HTMLVideoElement |
各平台浏览器兼容性
平台 | 浏览器类型 | 版本要求 | 兼容性 |
Mac | Safari | Safari 11或以上版本 | 支持 |
Chrome | Chrome 60或以上版本 | 支持 | |
Edge | Edge 80或以上版本 | 支持 | |
Windows | Chrome | Chrome 60或以上版本 | 支持 |
Edge | Edge 80或以上版本 | 支持 | |
iOS(11.1.2及以上版本) | Safari | Safari 11或以上版本 | 支持 |
Android | Chrome | Chrome 63或以上版本 | 支持 |
SDK暂不支持火狐浏览器;
由于H.264版权限制,SDK不支持华为系统的Chrome浏览器和以Chrome WebView为内核的浏览器。
其他浏览器及APP内置WebView兼容性请参照兼容性测试;
兼容性测试
左侧菜单进入【开发者中心】-【项目管理】,点击卡片上的【配置】进入配置页;

在配置页点击【保存并测试】,耐心等待数字人加载;若数字人拉流成功,且与数字人对话成功(针对互动数字人),说明浏览器兼容性没有问题;
