This topic describes how to use Alibaba Cloud resources to create your own application that is based on ApsaraVideo Real-time Communication (ARTC).
Procedure
Step | Description |
Create an ARTC application in the ApsaraVideo Live console. Then, obtain the application ID and AppKey. Note
| |
After you obtain the application ID and AppKey, use them and other parameters to generate authentication code. The code is provided by Alibaba Cloud based on your programming language. Then, integrate the code into the server. | |
After you complete the server-side configurations, use CocoaPods (for iOS) or Maven (for Android) to integrate the SDK.
|
Step 1: Create an application
Log on to the ApsaraVideo Live console.
In the left-side navigation pane, choose Live + > ApsaraVideo Real-time Communication > Applications.
Click Create Application.
Enter a custom name in the Instance Name field, select Terms of Service, and then click Buy Now.
After the application is created, refresh the Applications page to view the application.
NoteBy default, no fees are incurred when you create an application. You are charged based on your actual usage in the cloud. For more information, see Billing of ARTC.
Step 2: Integrate authentication code into the server
Integrate the authentication code provided by Alibaba Cloud into your server environment. For more information, see Token-based authentication.
The server provides API operations to facilitate calls on the mobile client.
Step 3: Integrate the SDK
ARTC provides the interactive mode that is suitable for interactive entertainment scenarios and the communication mode that is suitable for one-to-one or one-to-many communication scenarios. By choosing the right mode, you can ensure a smooth user experience and use the network resources in an efficient manner. We recommend that you choose a mode based on your business requirements.
Mode | Stream ingest | Stream pulling | Description |
Interactive mode |
| No role restrictions are imposed. All users have the permissions to perform stream pulling. |
|
Communication mode | No role restrictions are imposed. All users have the permissions to perform stream ingest. | No role restrictions are imposed. All users have the permissions to perform stream pulling. |
|
1. Project configuration
Android
We recommend that you use a Maven repository to integrate the required dependency libraries.
Add the URL of the Maven repository to the project-level
build.gradle
file.allprojects { repositories { google() jcenter() // Add the URL of the Maven repository that is required by ARTC. maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" } } }
In the application-level build.gradle file, add the following line of code.
// Add ARTC SDK as a dependency. implementation 'com.aliyun.aio:AliVCSDK_ARTC:${latest version}'
Add the following code to the app/src/main/AndroidManifest.xml file to obtain the required device permissions.
<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" />
NoteThe following permissions are requested at runtime:
Manifest.permission.CAMERA
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.RECORD_AUDIO
Manifest.permission.READ_EXTERNAL_STORAGE
If the operating system is Android 12 or later (API level 31 or higher), the following permission is also requested at runtime:
Manifest.permission.BLUETOOTH_CONNECT
(Optional) Add obfuscation rules.
-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.** { *; }
Verify that the configurations are complete.
iOS
We recommend that you use CocoaPods.
Open Terminal and run the following command to install CocoaPods.
ImportantBefore you start using CocoaPods, make sure that a Ruby environment is set up on your Mac.
sudo gem install cocoapods
In Terminal, run the following command to create a Podfile in the project path:
pod init
Edit the Podfile to add ARTC SDK as a dependency.
pod 'AliVCSDK_ARTC', '~> ${latest version}'
In Terminal, run the following command to update the CocoaPods dependency library in your project. A project file that is suffixed with .xcworkspace is generated. Double-click the file to install the SDK.
pod update
Grant permissions.
ImportantMake sure that permissions on your microphone and camera are granted.
Add the following configurations for permissions on the microphone and camera to the Info.plist file: Privacy - Camera Usage Description and Privacy - Microphone Usage Description.
Enable audio recording in the background by selecting Audio, AirPlay, and Picture in Picture, as shown in the following figure.
Find the Enable Bitcode option and set the value to No to disable Bitcode.
Windows
We recommend that you use Visual Studio 2015.
Add the directory of the runtime library to the include path.
Specify the path of the runtime library.
HarmonyOS
Prerequisites
Before integrating the SDK, make sure that the following requirements are met:
Contact the Huawei sales team to obtain necessary permissions for DevEco Studio 5.0.3.900 Release or later.
Obtain HarmonyOS NEXT SDK that supports API 12 or later.
Obtain HarmonyOS NEXT 5.0.0.102 that supports API 12 or later. Enable Allow Debugging on the HarmonyOS device that supports audio and video services.
For information about how to set up on-device debugging, see the HarmonyOS documentation.
Connect to the Internet on the HarmonyOS device.
Register a HUAWEI ID and complete identity verification.
Configure the project
Manual integration
Download the AliVCSDK_ARTC-6.11.0-Beta.har file. Add it to the libs directory in the project. Then, configure dependencies in the project. Sample code:
"dependencies": { "@aliyun_video_cloud/alivcsdk_artc":"file:./libs/AliVCSDK_ARTC-6.11.0-beta.har", }
OHPM integration
Configure dependencies in the project. Sample code:
"dependencies": { "@aliyun_video_cloud/alivcsdk_artc":"6.11.0-beta", }
Run the following command:
ohpm install @aliyun_video_cloud/alivcsdk_artc
2. SDK integration
1. Initialize the ARTC engine and register callbacks
When an exception occurs in the SDK, the SDK is designed to preferentially perform retries to restore the normal state. For exceptions that the SDK cannot handle, the SDK sends explicit callback notifications.
Exception | Callback | Solution | Remarks |
Failed authentication | onJoinChannelResult (AliRtcErrJoinBadToken returned) | When this exception occurs, check whether the token is valid in the app. | If authentication fails when the user proactively calls a method, the system returns an error message that indicates authentication failure in the callback. |
Authentication about to expire | onWillAuthInfoExpire | When this exception occurs, obtain the latest authentication information and then call refreshAuthInfo to refresh authentication. | The authentication exception occurs when the user proactively calls a method or when the program is running. The exception is returned in the callback corresponding to the method or an independent error callback. |
Expired authentication | onAuthInfoExpired | When this exception occurs, the user needs to use the app to re-join the channel. | The authentication exception occurs when the user proactively calls a method or when the program is running. The exception is returned in the callback corresponding to the method or an independent error callback. |
Network failure | onConnectionStatusChange (AliRtcConnectionStatusFailed returned) | When this exception occurs, the user needs to use the app to re-join the channel. | The SDK can automatically recover from network disconnection in a certain period of time. If the network is not recovered after the preset threshold time, a timeout is triggered and the SDK is interrupted. In this case, the user needs to check the network status of the app and join the channel again. |
Being kicked out | onBye |
| ARTC provides the capability that kicks users out of a channel. |
Local device exception | onLocalDeviceException | When this exception occurs, check the app permissions and check whether the device hardware is normal. | ARTC supports the device detection and exception diagnosis capabilities. When a local device exception that the SDK cannot handle occurs, the SDK sends callback notifications. In this case, the SDK cannot be recovered. Make sure that the device is normal so that the app can run normally. |
Android
private void createEngine() {
mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext());
mAliRtcEngine.setRtcEngineEventListener(new AliRtcEngineEventListener() {
/* The notification about the SDK connection to the server. You must handle connection failures. */
@Override
public void onConnectionStatusChange(AliRtcEngine.AliRtcConnectionStatus aliRtcConnectionStatus, AliRtcEngine.AliRtcConnectionStatusChangeReason aliRtcConnectionStatusChangeReason) {
super.onConnectionStatusChange(aliRtcConnectionStatus, aliRtcConnectionStatusChangeReason);
if (aliRtcConnectionStatus == AliRtcEngine.AliRtcConnectionStatus.AliRtcConnectionStatusFailed) {
/* TODO: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
} else {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
}
}
/* The SDK attempts to fix the local device exception. */
@Override
public void OnLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType aliRtcEngineLocalDeviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType aliRtcEngineLocalDeviceExceptionType, String s) {
super.OnLocalDeviceException(aliRtcEngineLocalDeviceType, aliRtcEngineLocalDeviceExceptionType, s);
/* TODO: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
}
@Override
public void onJoinChannelResult(int result, String channel, String userId, int elapsed) {
super.onJoinChannelResult(result, channel, userId, elapsed);
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
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() {
/* The callback is returned when authentication is about to expire in 30 seconds. You must refresh authentication. */
@Override
public void onAuthInfoWillExpire() {
super.onAuthInfoWillExpire();
/* TODO: Be sure to handle the exception. Obtain the authentication information of the channel and users, and then call refreshAuthInfo. */
}
/* The kicking-out operation may be triggered. You must handle the exception. */
@Override
public void onBye(int code) {
super.onBye(code);
/* TODO: We recommend that you perform handling operations based on your actual scenario. */
}
@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 = @"";
/* Construct the engine and pass in delegate. */
_engine = [AliRtcEngine sharedInstance:self extras:extras];
}
return _engine;
}
#pragma mark - "Delegates of engine"
/* The callback is returned when authentication is about to expire in 30 seconds. You must refresh authentication. */
- (void)onAuthInfoWillExpire{
/* TODO: Be sure to handle the exception. Obtain the authentication information of the channel and users, and then call refreshAuthInfo. */
}
/* The notification about the SDK connection to the server. You must handle connection failures. */
- (void)onConnectionStatusChange:(AliRtcConnectionStatus)status reason:(AliRtcConnectionStatusChangeReason)reason {
if (status == AliRtcConnectionStatusFailed) {
/* TODO: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
} else {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
}
}
/* The SDK attempts to fix the local device exception. */
- (void)onLocalDeviceException:(AliRtcLocalDeviceType)deviceType exceptionType:(AliRtcLocalDeviceExceptionType)exceptionType message:(NSString *_Nullable)msg {
/* TODO: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
}
/* The kicking-out operation may be triggered. You must handle the exception. */
/* The kicking-out operation may be triggered. You must handle the exception. */
- (void)onBye:(int)code {
/* TODO: We recommend that you perform handling operations based on your actual scenario. */
}
/* The notification about remote stream ingest. If automatic subscription is enabled, you can configure the black screen time and time to first frame for adaption. */
- (void)onRemoteTrackAvailableNotify:(NSString *_Nonnull)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
/* TODO: Be sure to handle the exception. Set a video rendering window for the 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 {
/* Clear the rendering window of the remote user. However, the remote user may directly leave the channel. */
[self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackCamera];
}
});
}
- (void)onRemoteUserOffLineNotify:(NSString *)uid offlineReason:(AliRtcUserOfflineReason)reason {
dispatch_async(dispatch_get_main_queue(), ^{
/* Clear the rendering window of the remote user. */
[self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackBoth];
});
}
- (void)onJoinChannelResult:(int)result channel:(NSString *)channel userId:(NSString *)userId elapsed:(int)elapsed {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
}
- (void)onLeaveChannelResult:(int)result stats:(AliRtcStats)stats {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
}
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: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
} else {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
}
};
virtual void OnLocalDeviceException(AliEngineLocalDeviceType deviceType, AliEngineLocalDeviceExceptionType exceptionType, const char* msg) override {
/* TODO: Be sure to handle the exception. The SDK has tried various recovery policies but still cannot recover. */
};
virtual void OnJoinChannelResult(int result, const char *channel, const char *userId, int elapsed) override {
/* TODO: Handle the exception as needed. Business code is added, usually for data statistics and UI changes. */
};
virtual void OnLeaveChannelResult(int result, AliEngineStats stats) override {
};
virtual void OnAuthInfoWillExpire() override {
/* TODO: Be sure to handle the exception. Obtain the authentication information of the channel and users, and then call refreshAuthInfo. */
};
virtual void OnBye(int code) override {
/* TODO: We recommend that you perform handling operations based on your actual scenario. */
};
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;
/* The window handle. */
HWND mHWnd;
};
private:
void createEngine() {
mAliRtcEngine = AliRtcEngine.Create("");
mLisenter = new AliEngineEventListenerImpl(mAliRtcEngine, mHWnd);
mAliRtcEngine->SetEngineEventListener(mLisenter);
}
HarmonyOS
this.rtcSdk = AliRtcEngine.getInstance(NULL, getContext(this));
this.engineEventListener: AliRtcEngineEventListener = new AliRtcEngineEventListener();
this.engineEventListener
.onRemoteUserOnline((uid: string, elapsed: boolean)=> {
// Triggered when a remote user joins the channel
})
.onRemoteUserOffline((uid:string, reason: AliRtcUserOfflineReason)=> {
// Triggered when a remote user leaves the channel
})
.onJoinChannel((result : number, channel : string, userId : string, elapsed : number)=> {
// Triggered when you joins the channel
})
.onLeaveChannel((result : number, stat : AliRtcStats)=> {
// Triggered when you leaves the channel
})
.onBye((code : AliRtcOnByeType)=> {
// Triggered when you are kicked out of the server or the channel is closed
})
.onOccurError((error : number, msg : string)=> {
// Triggered when an error occurs
})
.onConnectionStatusChange((status : number, reason : number)=> {
// Triggered when the network connection status changes
})
;
this.rtcSdk?.setRtcEngineEventListener(this.engineEventListener);
2. Configure parameters before users join a channel
By default, for a streamer in interactive mode, the SDK ingests local audio and video streams of the streamer and pulls audio and video streams of other streamers.
By default, for a viewer in interactive mode, the SDK does not ingest local audio and video streams of the viewer but pulls audio and video streams of streamers.
By default, the SDK performs automatic stream ingest and pulling. You can disable automatic stream ingest and pulling based on your business requirements.
Android
private void initEngineBeforeJoin() {
/* (Optional) Configure parameters before users join the channel. */
mAliRtcEngine.setChannelProfile(AliRtcEngine.AliRTCSdkChannelProfile.AliRTCSdkInteractiveLive);
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* Set the audio properties. */
mAliRtcEngine.setAudioProfile(AliRtcEngine.AliRtcAudioProfile.AliRtcEngineStereoHighQualityMode, AliRtcEngine.AliRtcAudioScenario.AliRtcSceneMusicMode);
/* (Optional) Configure camera preview. If you do not configure camera preview, stream ingest is also performed. */
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 {
/* (Optional) Configure parameters before users join the channel. */
[self.engine setChannelProfile:AliRtcInteractivelive];
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* Set the audio properties. */
[self.engine setAudioProfile:AliRtcEngineStereoHighQualityMode audio_scene:AliRtcSceneMusicMode];
/* (Optional) Configure camera preview. If you do not configure camera preview, stream ingest is also performed. */
AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
canvas.view = self.previewView;
canvas.renderMode = AliRtcRenderModeAuto;
[self.engine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackCamera];
return;
}
Windows
private:
void initEngineBeforeJoin() {
/* (Optional) Configure parameters before users join the channel. */
mAliRtcEngine->SetChannelProfile(AliEngineInteractiveLive);
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* Set the audio properties. */
mAliRtcEngine->SetAudioProfile(AliEngineBasicQualityMode, AliEngineSceneMusicMode);
/* (Optional) Configure camera preview. If you do not configure camera preview, stream ingest is also performed. */
AliEngineVideoCanvas canvas;
/* The window handle. */
canvas.view = mHWnd;
mAliRtcEngine.setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
}
HarmonyOS
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. Users joining the channel
After users join the channel, stream ingest and pulling are performed based on the parameters that you configured.
By default, the SDK automatically ingests and pulls streams to reduce the number of required API calls.
Android
initEngineBeforeJoin();
mAliRtcEngine.joinChannel("Authentication information", null, null, "testUserName");
iOS
[self initBeforeJoin];
/* The channel ID and user ID are issued by the server. The app does not obtain the IDs. */
[self.engine joinChannel:@"Authentication information" channelId:nil userId:nil name:@"testUserName" onResultWithUserId:nil];
Windows
initEngineBeforeJoin();
mAliRtcEngine->joinChannel("Authentication information", null, null, "testUserName");
HarmonyOS
this.initEngineBeforeJoin();
this.rtcSdk?.joinChannel("Authentication information", null, null, "testUserName");
4. Role switching
When a user switches from the streamer role to the viewer role (usually referred to as "get off the mic"), the system stops ingesting the local audio and video streams. The subscribed audio and video streams are not affected.
When a user switches from the viewer role to the streamer role (usually referred to as "get on the mic"), the system starts to ingest the local audio and video streams. The subscribed audio and video streams are not affected.
Android
/* TODO: Set the roles based on your business requirements. */
/* Set the streamer role. Users of this role participate in interaction. */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* Set the viewer role. Users of this role can only watch the stream. */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkLive);
iOS
/* TODO: Set the roles based on your business requirements. */
/* Set the streamer role. Users of this role participate in interaction. */
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* Set the viewer role. Users of this role can only watch the stream. */
[self.engine setClientRole:AliRtcClientRolelive];
Windows
/* TODO: Set the roles based on your business requirements. */
/* Set the streamer role. Users of this role participate in interaction. */
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* Set the viewer role. Users of this role can only watch the stream. */
mAliRtcEngine->SetClientRole(AliEngineClientRoleLive);
HarmonyOS
/* TODO: Set the roles based on your business requirements. */
/* Set the streamer role. Users of this role participate in interaction. */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleInteractive);
/* Set the viewer role. Users of this role can only watch the stream. */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleLive);
5. Users leaving the channel
Android
mAliRtcEngine.leaveChannel();
iOS
[self.engine leaveChannel];
Windows
mAliRtcEngine->LeaveChannel();
HarmonyOS
this.rtcSdk?.leaveChannel();
6. Destroy the engine
Android
mAliRtcEngine.destroy();
mAliRtcEngine = null;
iOS
[AliRtcEngine destroy];
Windows
mAliRtcEngine->Destroy();
mAliRtcEngine = nullptr;
HarmonyOS
AliRtcEngine.destroyInstance();
this.rtcSdk? = null;
Sample output
After the integration is complete based on the preceding code, the following output result is shown. You can adjust the code based on your business requirements.
Android
iOS
Windows
References
For more information about API calls, see Overview.