本文旨在指导您如何便捷地利用阿里云资源,创建属于自己的RTC应用。
操作流程
操作 | 说明 |
您可在视频直播控制台,创建实时音视频应用。创建完成后,获取Appid、Appkey。 说明
| |
获取Appid、Appkey后,服务器端根据开发语言拷贝阿里云提供的鉴权代码。 | |
完成服务器端的配置后,请使用CocoaPods(对于iOS)或Maven(对于Android)来集成并获取SDK。 |
步骤一:开通应用
步骤二:服务器集成
将阿里云提供的鉴权代码集成到您的服务器端环境中,以Java语言单参数入会为例,详情请参见Token鉴权。
服务器端提供API,方便移动应用(APP)端调用。
步骤三:SDK集成
根据具体的业务需求,可以选择适用于互动娱乐场景的互动模式,或者适合一对一或一对多广播的通信模式。正确的模式选择能够确保用户体验的流畅性并有效利用网络资源。您可以根据业务场景选择合适的模式。
模式 | 推流 | 拉流 | 模式介绍 |
互动模式 |
| 无角色限制,所有参与者都拥有拉流的权限。 |
|
通信模式 | 无角色限制,所有参与者都拥有推流权限。 | 无角色限制,所有参与者都拥有拉流的权限。 |
|
1. 工程化配置
Android端
推荐使用Maven仓库来集成所需的依赖库。
在根级别
build.gradle
文件中添加Maven仓库地址。allprojects { repositories { google() jcenter() //添加RTC需要的Maven地址 maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" } } }
在项目的app/build.gradle文件中,添加以下代码行。
//引入依赖的实时通信SDK (RTC SDK) implementation 'com.aliyun.aio:AliVCSDK_ARTC:${latest version}'
在app/src/main/AndroidManifest.xml文件中添加如下代码,获取相应的设备权限。
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Request legacy Bluetooth permissions on older devices. --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- Needed only if your app communicates with already-paired Bluetooth devices. --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
说明其中部分权限需要动态申请, 需要动态申请的权限包含:
Manifest.permission.CAMERA
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.RECORD_AUDIO
Manifest.permission.READ_EXTERNAL_STORAGE
当Android系统版本>=12(API_LEVEL>=31) 时, 需要额外动态申请以下权限:
Manifest.permission.BLUETOOTH_CONNECT
(可选)添加混淆规则。
-keep class com.aliyun.allinone.** { *; } -keep class com.aliyun.rts.network.AliHttpTool { *; } -keep class com.aliyun.common.AlivcBase { *; } -keep class com.huawei.multimedia.alivc.** { *; } -keep class com.alivc.rtc.** { *; } -keep class com.alivc.component.** { *; } -keep class org.webrtc.** { *; }
配置完成。
iOS端
推荐使用CocoaPods集成。
在终端窗口中输入以下命令,安装CocoaPods。
重要在开始使用CocoaPods之前,请确保您的Mac已经安装了Ruby环境。
sudo gem install cocoapods
进入项目所在路径,在终端窗口中输入以下命令,创建Podfile文件。
pod init
编辑Podfile文件,添加RTC SDK依赖。
pod 'AliVCSDK_ARTC', '~> ${latest version}'
在终端窗口中输入以下命令更新项目中的CocoaPods依赖库。执行完这个命令后,将生成一个包含集成SDK的.xcworkspace后缀的工程文件,双击该文件即可更新并安装SDK。
pod update
添加请求权限。
重要请务必添加录音权限和相机权限。
在Info.plist文件中添加摄像头和麦克风权限Privacy - Camera Usage Description、Privacy - Microphone Usage Description。
开启音频后台采集模式。如图所示,勾选Audio,AirPlay,and Picture in Picture即可。
找到Enable Bitcode选项,并将其设置为No来关闭Bitcode。
Windows端
推荐使用VS2015进行集成。
添加运行库的include路径。
添加运行库路径。
Linux端
Harmony端
环境准备
在开始集成阿里音视频SDK 前,请确保开发环境满足以下要求:
已联系华为商务人员,签署合作计划,开通相关权限,获取 DevEco Studio 5.0.3.900 Release 或以上版本。
获取配套 API Version 12的 HarmonyOS NEXT SDK 或以上版本。
获取配套 API Version 12的 HarmonyOS NEXT 5.0.0.102 操作系统或以上版本,支持音视频的鸿蒙设备,且已开启“允许调试”选项。
如果需要使用真机调试,请参考 鸿蒙官网文档 进行配置。
鸿蒙设备已经连接到 Internet。
已 注册华为开发者账号 并完成实名认证。
工程化配置
手动引入
下载AliVCSDK_ARTC-6.11.0-Beta.har包,放到工程libs中。在工程中配置引用:
"dependencies": { "@aliyun_video_cloud/alivcsdk_artc":"file:./libs/AliVCSDK_ARTC-6.11.0-beta.har", }
ohpm引入
在工程中配置:
"dependencies": { "@aliyun_video_cloud/alivcsdk_artc":"6.11.0-beta", }
运行命令:
ohpm install @aliyun_video_cloud/alivcsdk_artc
2. SDK集成
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需要介入以查看设备是否正常。 |
Android平台
private void createEngine() {
mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext());
mAliRtcEngine.setRtcEngineEventListener(new AliRtcEngineEventListener() {
/* SDK与服务器的链接状态通知,务必处理链接失败的情况 */
@Override
public void onConnectionStatusChange(AliRtcEngine.AliRtcConnectionStatus aliRtcConnectionStatus, AliRtcEngine.AliRtcConnectionStatusChangeReason aliRtcConnectionStatusChangeReason) {
super.onConnectionStatusChange(aliRtcConnectionStatus, aliRtcConnectionStatusChangeReason);
if (aliRtcConnectionStatus == AliRtcEngine.AliRtcConnectionStatus.AliRtcConnectionStatusFailed) {
/* TODO: 务必处理;建议业务提示客户,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
} else {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
}
/* SDK尝试控制本地设备异常 */
@Override
public void OnLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType aliRtcEngineLocalDeviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType aliRtcEngineLocalDeviceExceptionType, String s) {
super.OnLocalDeviceException(aliRtcEngineLocalDeviceType, aliRtcEngineLocalDeviceExceptionType, s);
/* TODO: 务必处理;建议业务提示客户错误,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
}
@Override
public void onJoinChannelResult(int result, String channel, String userId, int elapsed) {
super.onJoinChannelResult(result, channel, userId, elapsed);
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
Log.i(TAG, "onJoinChannelResult result=" + result + ",channel=" + channel + ",userId=" + userId + ",elapsed=" + elapsed);
}
@Override
public void onLeaveChannelResult(int result, AliRtcEngine.AliRtcStats stats) {
super.onLeaveChannelResult(result, stats);
Log.i(TAG, "onLeaveChannelResult result=" + result);
}
});
mAliRtcEngine.setRtcEngineNotify(new AliRtcEngineNotify() {
/* 鉴权距离过期还有30s时会回调,务必进行鉴权时间刷新 */
@Override
public void onAuthInfoWillExpire() {
super.onAuthInfoWillExpire();
/* TODO: 务必处理;业务触发重新获取当前channel,user的鉴权信息,然后设置refreshAuthInfo即可 */
}
/* 业务可能会触发踢人的动作,所以这个地方也需要处理 */
@Override
public void onBye(int code) {
super.onBye(code);
/* TODO: 建议业务根据自己的场景,进行对应的处理 */
}
@Override
public void onRemoteUserOnLineNotify(String uid, int elapsed) {
super.onRemoteUserOnLineNotify(uid, elapsed);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",elapsed=" + elapsed);
}
@Override
public void onRemoteUserOffLineNotify(String uid, AliRtcEngine.AliRtcUserOfflineReason aliRtcUserOfflineReason) {
super.onRemoteUserOffLineNotify(uid, aliRtcUserOfflineReason);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",aliRtcUserOfflineReason=" + aliRtcUserOfflineReason);
}
@Override
public void onRemoteTrackAvailableNotify(String uid, AliRtcEngine.AliRtcAudioTrack aliRtcAudioTrack, AliRtcEngine.AliRtcVideoTrack aliRtcVideoTrack) {
super.onRemoteTrackAvailableNotify(uid, aliRtcAudioTrack, aliRtcVideoTrack);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",aliRtcAudioTrack=" + aliRtcAudioTrack + ",aliRtcVideoTrack=" + aliRtcVideoTrack);
mMainHandler.post(new Runnable() {
@Override
public void run() {
if (aliRtcVideoTrack == AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera
|| aliRtcVideoTrack == AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackBoth) {
AliRtcEngine.AliRtcVideoCanvas remote_canvas = new AliRtcEngine.AliRtcVideoCanvas();
SurfaceView remoteView = mAliRtcEngine.createRenderSurfaceView(mContext);
if (remoteView != null) {
remoteView.setZOrderOnTop(true);
remoteView.setZOrderMediaOverlay(true);
}
remote_canvas.view = remoteView;
mLocalSurfaceContainer.addView(remote_canvas.view, new FrameLayout.LayoutParams(
findViewById(R.id.local_surface_container).getWidth()/4,
findViewById(R.id.local_surface_container).getHeight()/4));
mAliRtcEngine.setRemoteViewConfig(remote_canvas,uid,AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
} else {
mAliRtcEngine.setRemoteViewConfig(null, uid, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
}
}
});
}
});
}
iOS平台
- (AliRtcEngine *)engine{
if (!_engine) {
NSString *extras = @"";
/* 构造引擎并传入delegate */
_engine = [AliRtcEngine sharedInstance:self extras:extras];
}
return _engine;
}
#pragma mark - "Delegates of engine"
/* 鉴权距离过期还有30s时会回调,务必进行鉴权时间刷新 */
- (void)onAuthInfoWillExpire{
/* TODO: 务必处理;业务触发重新获取当前channel\user的鉴权信息,然后设置refreshAuthInfo即可 */
}
/* SDK与服务器的链接状态通知,务必处理链接失败的情况 */
- (void)onConnectionStatusChange:(AliRtcConnectionStatus)status reason:(AliRtcConnectionStatusChangeReason)reason {
if (status == AliRtcConnectionStatusFailed) {
/* TODO: 务必处理;建议业务提示客户,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
} else {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
}
/* SDK尝试控制本地设备异常 */
- (void)onLocalDeviceException:(AliRtcLocalDeviceType)deviceType exceptionType:(AliRtcLocalDeviceExceptionType)exceptionType message:(NSString *_Nullable)msg {
/* TODO: 务必处理;建议业务提示客户错误,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
}
/* 业务可能会触发踢人的动作,所以这个地方也需要处理 */
/* 业务可能会触发踢人的动作,所以这个地方也需要处理 */
- (void)onBye:(int)code {
/* TODO: 建议业务根据自己的场景,进行对应的处理 */
}
/* 远端推流通知,自动订阅时这个时候设置窗口黑屏时间和首帧可以兼顾 */
- (void)onRemoteTrackAvailableNotify:(NSString *_Nonnull)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
/* TODO: 务必处理;给SDK设置一个视频渲染窗口 */
dispatch_async(dispatch_get_main_queue(), ^{
if (videoTrack & AliRtcVideoTrackCamera) {
AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
canvas.view = self.remoteRenderView;
canvas.renderMode = AliRtcRenderModeAuto;
[self.engine setRemoteViewConfig:canvas uid:uid forTrack:AliRtcVideoTrackCamera];
} else {
/* 这里清空远端用户的渲染窗口,但是有可能远端用户直接离会 */
[self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackCamera];
}
});
}
- (void)onRemoteUserOffLineNotify:(NSString *)uid offlineReason:(AliRtcUserOfflineReason)reason {
dispatch_async(dispatch_get_main_queue(), ^{
/* 这里也清空远端用户的渲染窗口 */
[self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackBoth];
});
}
- (void)onJoinChannelResult:(int)result channel:(NSString *)channel userId:(NSString *)userId elapsed:(int)elapsed {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
- (void)onLeaveChannelResult:(int)result stats:(AliRtcStats)stats {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
Windows平台
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);
}
Linux 平台
Harmony端
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默认是自动推拉流模式,用户也可以关闭自动推拉流模式。
Android平台
private void initEngineBeforeJoin() {
/* 可选:入会前的参数设置 */
mAliRtcEngine.setChannelProfile(AliRtcEngine.AliRTCSdkChannelProfile.AliRTCSdkInteractiveLive);
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* 设置音频的属性 */
mAliRtcEngine.setAudioProfile(AliRtcEngine.AliRtcAudioProfile.AliRtcEngineStereoHighQualityMode, AliRtcEngine.AliRtcAudioScenario.AliRtcSceneMusicMode);
/* 可选:摄像头预览,不设置也会进行推流 */
AliRtcEngine.AliRtcVideoCanvas canvas = new AliRtcEngine.AliRtcVideoCanvas();
canvas.view = mAliRtcEngine.createRenderSurfaceView(mContext);
mLocalSurfaceContainer.removeAllViews();
if (canvas.view != null) {
mLocalSurfaceContainer.addView(canvas.view, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
}
mAliRtcEngine.setLocalViewConfig(canvas, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
}
iOS平台
- (void)initBeforeJoin {
/* 可选:入会前的参数设置 */
[self.engine setChannelProfile:AliRtcInteractivelive];
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* 设置音频的属性 */
[self.engine setAudioProfile:AliRtcEngineStereoHighQualityMode audio_scene:AliRtcSceneMusicMode];
/* 可选:摄像头预览,不设置也会进行推流 */
AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
canvas.view = self.previewView;
canvas.renderMode = AliRtcRenderModeAuto;
[self.engine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackCamera];
return;
}
Windows平台
private:
void initEngineBeforeJoin() {
/* 可选:入会前的参数设置 */
mAliRtcEngine->SetChannelProfile(AliEngineInteractiveLive);
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* 设置音频的属性 */
mAliRtcEngine->SetAudioProfile(AliEngineBasicQualityMode, AliEngineSceneMusicMode);
/* 可选:摄像头预览,不设置也会进行推流 */
AliEngineVideoCanvas canvas;
/* windows 窗口句柄 */
canvas.view = mHWnd;
mAliRtcEngine.setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
}
Linux 平台
Harmony端
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数量。
Android平台
initEngineBeforeJoin();
mAliRtcEngine.joinChannel("您的鉴权信息", null, null, "testUserName");
iOS平台
[self initBeforeJoin];
/* 这个地方channlid,userid完全取决于服务器下发的值,app不感知 */
[self.engine joinChannel:@"您的鉴权信息" channelId:nil userId:nil name:@"testUserName" onResultWithUserId:nil];
Windows平台
initEngineBeforeJoin();
mAliRtcEngine->joinChannel("您的鉴权信息", null, null, "testUserName");
Linux平台
Harmony端
this.initEngineBeforeJoin();
this.rtcSdk?.joinChannel("您的鉴权信息", null, null, "testUserName");
4、切换角色
当用户从主播角色转换到观众角色时(通常被称作“下麦”),系统将停止推送本地的音视频流,已经订阅的音视频流不受影响。
当用户从观众播角色转换到主播角色时(通常被称作“上麦”),系统将会推送本地的音视频流,已经订阅的音视频流不受影响。
Android平台
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* 设置观看角色(观众角色) */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkLive);
iOS平台
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* 设置观看角色(观众角色) */
[self.engine setClientRole:AliRtcClientRolelive];
Windows平台
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* 设置观看角色(观众角色) */
mAliRtcEngine->SetClientRole(AliEngineClientRoleLive);
Linux平台
Harmony端
/* TODO: 根据业务设置角色 */
/* 设置参与互动角色(主播角色) */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleInteractive);
/* 设置观看角色(观众角色) */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleLive);
5、离会
6、销毁引擎
Android平台
mAliRtcEngine.destroy();
mAliRtcEngine = null;
iOS平台
[AliRtcEngine destroy];
Windows平台
mAliRtcEngine->Destroy();
mAliRtcEngine = nullptr;
Linux平台
Harmony端
AliRtcEngine.destroyInstance();
this.rtcSdk? = null;
效果展示
集成上述代码后,将得到如下结果,您也可以根据业务进行相应的调整。
Android平台
ios平台
Windows平台
其他API
更多API的调用,详情请参见实时音视频ARTC SDK。