本文档将介绍如何在您的Windows、Linux项目中集成 ARTC SDK, 快速实现一个简单的实时音视频互动App,适用于互动直播和视频通话等场景。
功能简介
在开始之前,了解以下几个关键概念会很有帮助:
ARTC SDK:这是阿里云的实时音视频产品,帮助开发者快速实现实时音视频互动的SDK。
GRTN:阿里云全球实时传输网络,提供超低延时、高音质、安全可靠的音视频通讯服务。
频道:相当于一个虚拟的房间,所有加入同一频道的用户都可以进行实时音视频互动。
主播:可在频道内发布音视频流,并可订阅其他主播发布的音视频流。
观众:可在频道内订阅音视频流,不能发布音视频流。
实现实时音视频互动的基本流程如下:
用户需要设置频道场景,并加入频道:
视频通话场景:所有用户都是主播角色,可以进行推流和拉流。
互动直播场景:需要在频道内推流的用户设置主播角色;如果用户只需要拉流,不需要推流,则设置观众角色。
加入频道后,不同角色的用户有不同的推拉流行为:
所有加入频道内的用户都可以接收频道内的音视频流。
主播角色可以在频道内推音视频流。
观众如果需要推流,需要将用户角色切换成主播,便可以推流。
创建应用
获取实时音视频应用的AppID和AppKey,详情请参见创建应用。
服务器集成
将阿里云提供的鉴权代码集成到您的服务器端环境中,详情请参见Token鉴权。
服务器端提供API,方便移动应用(APP)端调用。
功能实现
Windows
前提条件
Visual Studio 2015 或以上版本。
WIndows 7 或以上版本。
集成SDK
在SDK下载,获取最新的 ARTC SDK 文件。
解压 ARTC SDK 文件,并将目录下的文件拷贝到您的项目中。
配置项目属性:
在解决方案资源管理器窗口中,右键单击项目,进入“属性”界面。

添加包含目录:选择配置属性(Configuration Properties) → C/C++ → 常规(General),在附加包含目录(Additional Include Directories)中添加头文件路径。

添加库目录:在 Properties 窗口中,选择配置属性(Configuration Properties) → 链接器( Linker)→ 常规(General),在附加库目录( Additional Library Directories) 中添加库文件(.lib)的路径,例如
.../x64/Release。
指定链接库文件:在 Properties 窗口中,选择配置属性(Configuration Properties)→ 链接器( Linker)→ 输入(Input),在附加依赖项(Additional Dependencies)中添加需要链接的库文件名“AliRTCSdk.lib”。
实现步骤
1、初始化RTC引擎及回调注册
SDK设计为在遇到异常情况时,首先尝试内部重试机制以恢复正常状态。对于那些SDK无法自行解决的错误,会通过明确定义的回调接口(API)通知到您的应用程序。
异常发生原因 | 回调及参数 | 解决方案 | 说明 |
鉴权失败 | onJoinChannelResult回调中的result返回AliRtcErrJoinBadToken | 发生错误时App需要检查Token是否正确。 | 在用户主动调用API时,若鉴权失败,系统将在调用API的回调中返回鉴权失败的错误信息。 |
鉴权将要过期 | onWillAuthInfoExpire | 发生该异常时App需要重新获取最新的鉴权信息后,再调用refreshAuthInfo刷新鉴权信息。 | 鉴权过期错误在两种情况下出现:用户调用API或程序执行期间。因此,错误反馈将通过API回调或通过独立的错误回调通知。 |
鉴权过期 | onAuthInfoExpired | 发生该异常时App需要重新入会。 | 鉴权过期错误在两种情况下出现:用户调用API或程序执行期间。因此,错误反馈将通过API回调或通过独立的错误回调通知。 |
网络连接异常 | onConnectionStatusChange回调返回AliRtcConnectionStatusFailed。 | 发生该异常时APP需要重新入会。 | SDK具备一定时间断网自动恢复能力,但若断线时间超出预设阈值,会触发超时并断开连接。此时,App应检查网络状态并指导用户重新加入会议。 |
被踢下线 | onBye |
| RTC服务提供了管理员可以主动移除参与者的功能。 |
本地设备异常 | onLocalDeviceException | 发生该异常时App需要检测权限、设备硬件是否正常。 | RTC服务支持设备检测和异常诊断的能力;当本地设备发生异常时,RTC服务会通过回调的方式通知客户本地设备异常,此时,若SDK无法自行解决问题,则App需要介入以查看设备是否正常。 |
class AliEngineEventListenerImpl : public AliEngineEventListener {
public:
AliEngineEventListenerImpl(AliEngine* engine, HWND hWnd) {
mAliRtcEngine = engine;
mHWnd = hWnd;
};
virtual AliEngineEventListenerImpl() {};
virtual void OnConnectionStatusChange(int status, int reason) override {
if (status == AliEngineConnectionFailed) {
/* TODO: 务必处理;建议业务提示客户,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
} else {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
};
virtual void OnLocalDeviceException(AliEngineLocalDeviceType deviceType, AliEngineLocalDeviceExceptionType exceptionType, const char* msg) override {
/* TODO: 务必处理;建议业务提示客户错误,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
};
virtual void OnJoinChannelResult(int result, const char *channel, const char *userId, int elapsed) override {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
};
virtual void OnLeaveChannelResult(int result, AliEngineStats stats) override {
};
virtual void OnAuthInfoWillExpire() override {
/* TODO: 务必处理;业务触发重新获取当前channel,user的鉴权信息,然后设置refreshAuthInfo即可 */
};
virtual void OnBye(int code) override {
/* TODO: 建议业务根据自己的场景,进行对应的处理 */
};
virtual void OnRemoteUserOnLineNotify(const char *uid, int elapsed) override {
};
virtual void OnRemoteUserOffLineNotify(const char *uid, AliEngineUserOfflineReason reason) override {
};
virtual void OnRemoteTrackAvailableNotify(const char *uid,
AliEngineAudioTrack audioTrack,
AliEngineVideoTrack videoTrack) {
AliEngineVideoCanvas remote_canvas;
if (videoTrack == AliEngineVideoTrackCamera
|| videoTrack == AliEngineVideoTrackBoth) {
RECT rect;
::GetWindowRect(mHWnd, &rect);
remote_canvas.displayView = remoteView;
remote_canvas.renderMode = AliEngineRenderModeAuto;
mAliRtcEngine->SetRemoteViewConfig(remote_canvas,uid,AliEngineVideoTrackCamera);
} else {
mAliRtcEngine->SetRemoteViewConfig(remote_canvas, uid, AliEngineVideoTrackCamera);
}
}
private:
AliEngine* mAliRtcEngine = nullptr;
/* windows 窗口句柄 */
HWND mHWnd;
};
private:
void createEngine() {
mAliRtcEngine = AliRtcEngine.Create("");
mLisenter = new AliEngineEventListenerImpl(mAliRtcEngine, mHWnd);
mAliRtcEngine->SetEngineEventListener(mLisenter);
}2、设置入会前的参数
在互动模式和主播角色设定下,SDK默认会自动推送本地音视频流,并接收其他主播的音视频流。
在互动模式和观众角色设定下,SDK不会推送本地的音视频流,但会接收其他主播的音视频流。
SDK默认是自动推拉流模式,用户也可以关闭自动推拉流模式。
private:
void initEngineBeforeJoin() {
/* 可选:入会前的参数设置 */
mAliRtcEngine->SetChannelProfile(AliEngineInteractiveLive);
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* 设置音频的属性 */
mAliRtcEngine->SetAudioProfile(AliEngineBasicQualityMode, AliEngineSceneMusicMode);
/* 可选:摄像头预览,不设置也会进行推流 */
AliEngineVideoCanvas canvas;
/* windows 窗口句柄 */
canvas.view = mHWnd;
mAliRtcEngine.setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
}3、入会
入会后会按照入会前设定的参数执行相应的推流和拉流。
SDK默认会自动推拉流,以减少客户端需要调用的API数量。
initEngineBeforeJoin();
mAliRtcEngine->joinChannel("您的鉴权信息", null, null, "testUserName");4、切换角色
当用户从主播角色转换到观众角色时(通常被称作“下麦”),系统将停止推送本地的音视频流,已经订阅的音视频流不受影响。
当用户从观众播角色转换到主播角色时(通常被称作“上麦”),系统将会推送本地的音视频流,已经订阅的音视频流不受影响。
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* 设置观看角色(观众角色) */
mAliRtcEngine->SetClientRole(AliEngineClientRoleLive);5、离会
mAliRtcEngine->LeaveChannel();6、销毁引擎
mAliRtcEngine->Destroy();
mAliRtcEngine = nullptr;效果展示

参考信息
Linux
前提条件
实现步骤
1、初始化RTC引擎及回调注册
2、设置入会前的参数
在互动模式和主播角色设定下,SDK默认会自动推送本地音视频流,并接收其他主播的音视频流。
在互动模式和观众角色设定下,SDK不会推送本地的音视频流,但会接收其他主播的音视频流。
SDK默认是自动推拉流模式,用户也可以关闭自动推拉流模式。
3、入会
入会后会按照入会前设定的参数执行相应的推流和拉流。
SDK默认会自动推拉流,以减少客户端需要调用的API数量。
4、切换角色
当用户从主播角色转换到观众角色时(通常被称作“下麦”),系统将停止推送本地的音视频流,已经订阅的音视频流不受影响。
当用户从观众播角色转换到主播角色时(通常被称作“上麦”),系统将会推送本地的音视频流,已经订阅的音视频流不受影响。