本文档将介绍如何在您的Windows、Linux、Harmony项目中集成 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、切换角色
当用户从主播角色转换到观众角色时(通常被称作“下麦”),系统将停止推送本地的音视频流,已经订阅的音视频流不受影响。
当用户从观众播角色转换到主播角色时(通常被称作“上麦”),系统将会推送本地的音视频流,已经订阅的音视频流不受影响。
5、离会
6、销毁引擎
参考信息
Harmony
前提条件
已联系华为商务人员,签署合作计划,开通相关权限,获取 DevEco Studio 5.0.3.900 Release 或以上版本。
获取配套 API Version 12的 HarmonyOS NEXT 5.0.0.102 操作系统或以上版本,支持音视频的鸿蒙设备,且已开启“允许调试”选项。
如果需要使用真机调试,请参考 鸿蒙官网文档 进行配置。
鸿蒙设备已经连接到 Internet。
已 注册华为开发者账号 并完成实名认证。
集成SDK
ohpm自动集成(推荐)
在工程中配置:
"dependencies": {
"@aliyun_video_cloud/alivcsdk_artc":"6.11.0-beta",
}
运行命令:
ohpm install @aliyun_video_cloud/alivcsdk_artc
下载SDK手动集成
在SDK下载中下载最新版本的Harmony ARTC SDK ,放到工程libs中。在工程中配置引用:
"dependencies": {
"@aliyun_video_cloud/alivcsdk_artc":"file:./libs/AliVCSDK_ARTC-6.11.0-beta.har",
}
实现步骤
1、初始化RTC引擎及回调注册
this.rtcSdk = AliRtcEngine.getInstance(NULL, getContext(this));
this.engineEventListener: AliRtcEngineEventListener = new AliRtcEngineEventListener();
this.engineEventListener
.onRemoteUserOnline((uid: string, elapsed: boolean)=> {
//有人入会
})
.onRemoteUserOffline((uid:string, reason: AliRtcUserOfflineReason)=> {
//有人离会
})
.onJoinChannel((result : number, channel : string, userId : string, elapsed : number)=> {
// 入会时触发
})
.onLeaveChannel((result : number, stat : AliRtcStats)=> {
//离会时触发
})
.onBye((code : AliRtcOnByeType)=> {
// 被服务器踢出或者频道关闭时回调
})
.onOccurError((error : number, msg : string)=> {
// 发生错误时回调
})
.onConnectionStatusChange((status : number, reason : number)=> {
//网络连接变化时回调
})
;
this.rtcSdk?.setRtcEngineEventListener(this.engineEventListener);
2、设置入会前的参数
在互动模式和主播角色设定下,SDK默认会自动推送本地音视频流,并接收其他主播的音视频流。
在互动模式和观众角色设定下,SDK不会推送本地的音视频流,但会接收其他主播的音视频流。
SDK默认是自动推拉流模式,用户也可以关闭自动推拉流模式。
initEngineBeforeJoin = (surfaceId: string) => {
let encoderConfig : AliRtcVideoEncoderConfiguration = new AliRtcVideoEncoderConfiguration();
encoderConfig.dimensions = new AliRtcVideoDimensions();
encoderConfig.dimensions.width = 480
encoderConfig.dimensions.height = 640
encoderConfig.frameRate = AliRtcFrameRate.AliEngineFrameRateFps15
this.rtcSdk?.setVideoEncoderConfiguration(encoderConfig)
let profile : AliRtcChannelProfile = AliRtcChannelProfile.AliEngineInteractiveLive
if (this.mainPageParams.interactive_mode == 0) {
profile = AliRtcChannelProfile.AliEngineCommunication
} else if (this.mainPageParams.interactive_mode == 2) {
profile = AliRtcChannelProfile.AliEngineInteractiveWithLowLatencyLive
}
this.rtcSdk?.setChannelProfile(profile);
this.rtcSdk?.setClientRole(this.mainPageParams.is_anchor ? AliRtcClientRole.AliEngineClientRoleInteractive : AliRtcClientRole.AliEngineClientRoleLive);
this.localVideoCanvas.surfaceId = surfaceId;
this.rtcSdk?.setLocalViewConfig(this.localVideoCanvas, this.componentController, AliRtcVideoTrack.AliEngineVideoTrackCamera);
}
3、入会
入会后会按照入会前设定的参数执行相应的推流和拉流。
SDK默认会自动推拉流,以减少客户端需要调用的API数量。
this.initEngineBeforeJoin();
this.rtcSdk?.joinChannel("您的鉴权信息", null, null, "testUserName");
4、切换角色
当用户从主播角色转换到观众角色时(通常被称作“下麦”),系统将停止推送本地的音视频流,已经订阅的音视频流不受影响。
当用户从观众播角色转换到主播角色时(通常被称作“上麦”),系统将会推送本地的音视频流,已经订阅的音视频流不受影响。
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleInteractive);
/* 设置观看角色(观众角色) */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleLive);
5、离会
this.rtcSdk?.leaveChannel();
6、销毁引擎
AliRtcEngine.destroyInstance();
this.rtcSdk? = null;