All Products
Search
Document Center

:Quick Start ApsaraVideo Real-time Communication

Last Updated:Mar 06, 2026

This topic describes how to create an ApsaraVideo Real-time Communication (ARTC) application using Alibaba Cloud resources.

Operation Flow

Operation

Description

Step 1: Activate the application

Create an ApsaraVideo Real-time Communication application in the ApsaraVideo Live console. After creation, obtain the Appid and Appkey.

Note
  • Instance names support Chinese and English characters.

  • Activating an application does not incur charges by default. You are charged based on your actual usage on the cloud.

Step 2: Server integration

After obtaining the Appid and Appkey, copy the authentication code provided by Alibaba Cloud to your server based on your development language.

Step 3: SDK integration

After configuring the server, use CocoaPods (for iOS) or Maven (for Android) to integrate and obtain the SDK.

Step 1: Activate the application

  1. Log on to the ApsaraVideo Live console.

  2. In the navigation pane on the left, click Live + > ApsaraVideo Real-time Communication > Applications.

  3. Click Create Application.

  4. Enter a custom instance name, select the Terms of Service checkbox, and then click Buy Now.

  5. After a success message is displayed, you can refresh the Application Management page to view your new ApsaraVideo Real-time Communication application.

    Note

    By default, creating an application does not incur charges. You are charged based on your actual usage. For more information, see Audio and Video Call Fees.

Step 2: Server integration

  1. Integrate the authentication code that is provided by Alibaba Cloud into your server environment. For example, for information about joining a channel with a single parameter in Java, see Token Authentication.

  2. The server provides APIs for mobile applications to invoke.

Step 3: SDK integration

Choose the appropriate mode based on your business scenario. You can select the interactive mode for interactive entertainment or the communication mode for one-to-one or one-vs.-all broadcasts. Selecting the correct mode ensures a smooth user experience and efficient resource usage.

Mode

Stream Ingest

Stream Pulling

Mode Description

Interactive Mode

  • Role restrictions apply. Only users assigned the streamer role can ingest streams.

  • Participants can flexibly switch roles throughout the process.

No role restrictions apply. All participants have permission to pull streams.

  • In interactive mode, events such as a streamer joining or leaving a meeting, or starting to ingest a live stream, are immediately broadcast to viewers. This ensures viewers are promptly informed of the streamer's activities. Conversely, viewer activities are not broadcast to the streamer, maintaining an uninterrupted live stream for the streamer.

  • In interactive mode, the streamer role manages live interactions, while the viewer role primarily receives content and typically does not participate in the live interaction process. If future business requirements might change, making it uncertain whether viewer interaction support is needed, use interactive mode by default. This mode offers high flexibility, allowing you to adapt to different interaction needs by adjusting user role permissions.

Communication Mode

No role restrictions apply. All participants have permission to ingest streams.

No role restrictions apply. All participants have permission to pull streams.

  • In communication mode, meeting participants are aware of each other's presence.

  • Although this mode does not distinguish user roles, it corresponds to the streamer role in interactive mode. The goal is to simplify operations, allowing users to achieve desired functionality by invoking fewer APIs.

1. Engineering Configuration

Android

Use Maven repositories to integrate the required dependency libraries.

  1. Add the Maven repository address to the root-level build.gradle file.

    allprojects {
        repositories {
            google()
            jcenter()
            // Add the Maven address required by RTC
            maven {
                url "https://maven.aliyun.com/nexus/content/repositories/releases"
            }
        }
    }
  2. In the app/build.gradle file of your project, add the following lines of code.

    // Import the dependent real-time communication SDK (RTC SDK) 
    implementation 'com.aliyun.aio:AliVCSDK_ARTC:${latest version}'
  3. In the app/src/main/AndroidManifest.xml file, add the following code 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" />
    Note

    Some permissions, such as the following, require dynamic requests:

    • Manifest.permission.CAMERA

    • Manifest.permission.WRITE_EXTERNAL_STORAGE

    • Manifest.permission.RECORD_AUDIO

    • Manifest.permission.READ_EXTERNAL_STORAGE

    If the Android system version is 12 or later (API_LEVEL 31 or later), dynamically request the following additional permissions:

    • Manifest.permission.BLUETOOTH_CONNECT

  4. (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.** {
    *;
    }
  5. The configuration is complete.

iOS

Use CocoaPods for integration.

  1. In the terminal window, enter the following command to install CocoaPods.

    Important

    Before you use CocoaPods, make sure that Ruby is installed on your Mac.

    sudo gem install cocoapods
  2. Navigate to your project path and run the following command in the terminal window to create a Podfile.

    pod init
  3. Edit the Podfile and add the RTC SDK dependency.

    pod 'AliVCSDK_ARTC', '~> ${latest version}'
  4. Run the following command in the terminal window to update the CocoaPods dependencies in your project. After the command is run, a project file with the `.xcworkspace` suffix is generated. This file contains the integrated SDK. Double-click this file to update and install the SDK.

    pod update
  5. Add permission requests.

    Important

    Add recording and camera permissions.

    1. In the Info.plist file, add the camera and microphone permissions: Privacy - Camera Usage Description and Privacy - Microphone Usage Description.

      image.png

    2. Enable the background audio capture mode. As shown in the following figure, select Audio, AirPlay, and Picture in Picture.

      image.png

  6. Find the Enable Bitcode option, and set it to No to disable Bitcode.

    image.png

Windows

Use Visual Studio 2015 (VS2015) for integration.

  1. Add the include path for the runtime library.imageimage

  2. Add the runtime library path.image

Harmony client

  1. Environment Preparations

    Before you integrate the ApsaraVideo SDK for Alibaba Cloud, make sure that your development environment meets the following requirements:

    • Contact Huawei business personnel to sign a cooperation plan, activate the relevant permissions, and obtain DevEco Studio 5.0.3.900 Release or later.

    • Obtain HarmonyOS NEXT SDK API Version 12 or later.

    • Obtain HarmonyOS NEXT 5.0.0.102 operating system (API Version 12 or later). The operating system must support audio and video on HarmonyOS devices and have the "Allow debugging" option enabled.

    • To debug on a real device, configure the device. For more information, see the HarmonyOS official documentation.

    • The HarmonyOS device is connected to the Internet.

    • You have registered a Huawei Developer account and completed identity verification.

  2. Engineering Configuration
    1. Manual Import

      Download the `AliVCSDK_ARTC-6.11.0-Beta.har` package and place it in the `libs` folder of the project. Then, configure the reference in your project:

      "dependencies": {
          "@aliyun_video_cloud/alivcsdk_artc":"file:./libs/AliVCSDK_ARTC-6.11.0-beta.har",
        }

      image

    2. ohpm Import

      Configure the project:

      "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 RTC engine and register callbacks

Important

The SDK is designed to use internal retry mechanisms to recover from exceptions. If the SDK cannot resolve an error, it notifies your application through callback interfaces (APIs).

Cause of Exception

Callback and Parameters

Solution

Description

Authentication failed

onJoinChannelResult callback returns AliRtcErrJoinBadToken

If an error occurs, the app must check if the Token is correct.

If authentication fails when a user actively invokes an API, the system returns an authentication failure error message in the API invocation callback.

Authentication will expire

onWillAuthInfoExpire

If this exception occurs, the app must re-obtain the latest authentication information and then invoke refreshAuthInfo to refresh the authentication information.

Authentication expiration errors occur in two scenarios: when a user invokes an API or during program execution. Therefore, error feedback is provided through API callbacks or independent error callbacks.

Authentication expired

onAuthInfoExpired

If this exception occurs, the app must rejoin the channel.

Authentication expiration errors occur in two scenarios: when a user invokes an API or during program execution. Therefore, error feedback is provided through API callbacks or independent error callbacks.

Network connection abnormal

onConnectionStatusChange callback returns AliRtcConnectionStatusFailed.

If this exception occurs, the app must rejoin the channel.

The SDK has an automatic recovery capability for temporary network disconnections. However, if the disconnection duration exceeds the preset threshold, a timeout is triggered, and the connection is lost. In this case, the app should check the network status and guide the user to rejoin the meeting.

Kicked offline

onBye

  • AliRtcOnByeUserReplaced: If this exception occurs, check if the user ID is the same.

  • AliRtcOnByeBeKickedOut: If this exception occurs, it indicates that you were kicked offline by the service. Rejoin the channel.

  • AliRtcOnByeChannelTerminated: If this exception occurs, it indicates that the channel was destroyed. Rejoin the channel.

The RTC service provides a feature that allows administrators to actively remove participants.

On-premises device abnormal

onLocalDeviceException

If this exception occurs, the app must check if permissions and device hardware are normal.

The RTC service supports device detection and abnormal diagnosis. If an on-premises device experiences an exception, the RTC service notifies the client of the on-premises device exception through a callback. If the SDK cannot resolve the issue on its own, the app must intervene to check if the device is normal.

Android

private void createEngine() {
    mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext());
    mAliRtcEngine.setRtcEngineEventListener(new AliRtcEngineEventListener() {

        /* Notification of SDK connection status to the server. Handle connection failures. */
        @Override
        public void onConnectionStatusChange(AliRtcEngine.AliRtcConnectionStatus aliRtcConnectionStatus, AliRtcEngine.AliRtcConnectionStatusChangeReason aliRtcConnectionStatusChangeReason) {
            super.onConnectionStatusChange(aliRtcConnectionStatus, aliRtcConnectionStatusChangeReason);
            if (aliRtcConnectionStatus == AliRtcEngine.AliRtcConnectionStatus.AliRtcConnectionStatusFailed) {
                /* TODO: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
            } else {
                /* TODO: Optional. Add business logic, typically for data statistics or UI changes. */
            }
        }

        /* The SDK attempts to control on-premises device exceptions. */
        @Override
        public void OnLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType aliRtcEngineLocalDeviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType aliRtcEngineLocalDeviceExceptionType, String s) {
            super.OnLocalDeviceException(aliRtcEngineLocalDeviceType, aliRtcEngineLocalDeviceExceptionType, s);
            /* TODO: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
        }

        @Override
        public void onJoinChannelResult(int result, String channel, String userId, int elapsed) {
            super.onJoinChannelResult(result, channel, userId, elapsed);
            /* TODO: Optional. Add business logic, typically for data statistics or 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() {

        /* Callback when authentication is 30 seconds from expiring. Refresh authentication time. */
        @Override
        public void onAuthInfoWillExpire() {
            super.onAuthInfoWillExpire();
            /* TODO: Required. The service triggers re-obtaining authentication information for the current channel and user, then set refreshAuthInfo. */
        }

        /* The service might trigger kicking users, so handle this as well. */
        @Override
        public void onBye(int code) {
            super.onBye(code);
            /* TODO: Handle this based on your business 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 the delegate. */
        _engine = [AliRtcEngine sharedInstance:self extras:extras];
    }
    return _engine;
}

#pragma mark - "Delegates of engine"
/* Callback when authentication is 30 seconds from expiring. Refresh authentication time. */
- (void)onAuthInfoWillExpire{
    /* TODO: Required. The service triggers re-obtaining authentication information for the current channel and user, then set refreshAuthInfo. */
}

/* Notification of SDK connection status to the server. Handle connection failures. */
- (void)onConnectionStatusChange:(AliRtcConnectionStatus)status reason:(AliRtcConnectionStatusChangeReason)reason {
    if (status == AliRtcConnectionStatusFailed) {
        /* TODO: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
    } else {
        /* TODO: Optional. Add business logic, typically for data statistics or UI changes. */
    }
}

/* The SDK attempts to control on-premises device exceptions. */
- (void)onLocalDeviceException:(AliRtcLocalDeviceType)deviceType exceptionType:(AliRtcLocalDeviceExceptionType)exceptionType message:(NSString *_Nullable)msg {
    /* TODO: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
}

/* The service might trigger kicking users, so handle this as well. */
/* The service might trigger kicking users, so handle this as well. */
- (void)onBye:(int)code {
    /* TODO: Handle this based on your business scenario. */
}

/* Remote stream ingest notification. When auto-subscribing, set the black screen time and first frame time concurrently. */
- (void)onRemoteTrackAvailableNotify:(NSString *_Nonnull)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
    /* TODO: Required. 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 remote user's rendering window here, but the remote user might leave the channel directly. */
            [self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackCamera];
        }
    });
}

- (void)onRemoteUserOffLineNotify:(NSString *)uid offlineReason:(AliRtcUserOfflineReason)reason {
    dispatch_async(dispatch_get_main_queue(), ^{
        /* Clear the remote user's rendering window here as well. */
        [self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackBoth];
    });
}

- (void)onJoinChannelResult:(int)result channel:(NSString *)channel userId:(NSString *)userId elapsed:(int)elapsed {
    /* TODO: Optional. Add business logic, typically for data statistics or UI changes. */
}

- (void)onLeaveChannelResult:(int)result stats:(AliRtcStats)stats {
    /* TODO: Optional. Add business logic, typically for data statistics or 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: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
        } else {
            /* TODO: Optional. Add business logic, typically for data statistics or UI changes. */
        }
    };

    virtual void OnLocalDeviceException(AliEngineLocalDeviceType deviceType, AliEngineLocalDeviceExceptionType exceptionType, const char* msg) override {
        /* TODO: Required. Prompt the customer with an error message. The SDK reports this only after internal recovery policies have failed and it can no longer be used. */
    };

    virtual void OnJoinChannelResult(int result, const char *channel, const char *userId, int elapsed) override {
        /* TODO: Optional. Add business logic, typically for data statistics or UI changes. */
    };

    virtual void OnLeaveChannelResult(int result, AliEngineStats stats) override {
        
    };

    virtual void OnAuthInfoWillExpire() override {
        /* TODO: Required. The service triggers re-obtaining authentication information for the current channel and user, then set refreshAuthInfo. */
    };

    virtual void OnBye(int code) override {
        /* TODO: Handle this based on your business 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;
    /* Windows window handle */
    HWND mHWnd;
};


private:
void createEngine() {
    mAliRtcEngine = AliRtcEngine.Create("");
    mLisenter = new AliEngineEventListenerImpl(mAliRtcEngine, mHWnd);
    mAliRtcEngine->SetEngineEventListener(mLisenter);
}

Harmony client

this.rtcSdk = AliRtcEngine.getInstance(NULL, getContext(this));
this.engineEventListener: AliRtcEngineEventListener = new AliRtcEngineEventListener();
this.engineEventListener
      .onRemoteUserOnline((uid: string, elapsed: boolean)=> {
        // Someone joined the channel
      })
      .onRemoteUserOffline((uid:string, reason: AliRtcUserOfflineReason)=> {
        // Someone left the channel
      })
      .onJoinChannel((result : number, channel : string, userId : string, elapsed : number)=> {
        // Triggered when joining the channel
      })
      .onLeaveChannel((result : number, stat : AliRtcStats)=> {
        // Triggered when leaving the channel
      })
      
      .onBye((code : AliRtcOnByeType)=> {
        // Callback when kicked out by the server or the channel is closed
      })
      .onOccurError((error : number, msg : string)=> {
        // Callback when an error occurs
      })
      
      .onConnectionStatusChange((status : number, reason : number)=> {
        // Callback when network connection changes
      })
    ;

  this.rtcSdk?.setRtcEngineEventListener(this.engineEventListener);

2. Set parameters before joining the channel

Important
  • In interactive mode, if a user has the streamer role, the SDK automatically ingests local audio and video streams and receives audio and video streams from other streamers by default.

  • In interactive mode, if a user has the viewer role, the SDK does not ingest local audio or video streams but receives audio and video streams from other streamers.

  • By default, the SDK uses the automatic stream ingest and subscription mode. You can also disable this mode.

Android

    private void initEngineBeforeJoin() {
        /* Optional: Parameter settings before joining the channel */
        mAliRtcEngine.setChannelProfile(AliRtcEngine.AliRTCSdkChannelProfile.AliRTCSdkInteractiveLive);
        mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
        /* Set audio properties */
        mAliRtcEngine.setAudioProfile(AliRtcEngine.AliRtcAudioProfile.AliRtcEngineStereoHighQualityMode, AliRtcEngine.AliRtcAudioScenario.AliRtcSceneMusicMode);

        /* Optional: Camera preview. Streams are ingested even if not set. */
        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: Parameter settings before joining the channel */
    [self.engine setChannelProfile:AliRtcInteractivelive];
    [self.engine setClientRole:AliRtcClientRoleInteractive];
    /* Set audio properties */
    [self.engine setAudioProfile:AliRtcEngineStereoHighQualityMode audio_scene:AliRtcSceneMusicMode];
    /* Optional: Camera preview. Streams are ingested even if not set. */
    AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
    canvas.view = self.previewView;
    canvas.renderMode = AliRtcRenderModeAuto;
    [self.engine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackCamera];
    return;
}

Windows

private:
void initEngineBeforeJoin() {
    /* Optional: Parameter settings before joining the channel */
    mAliRtcEngine->SetChannelProfile(AliEngineInteractiveLive);
    mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
    /* Set audio properties */
    mAliRtcEngine->SetAudioProfile(AliEngineBasicQualityMode, AliEngineSceneMusicMode);

    /* Optional: Camera preview. Streams are ingested even if not set. */
    AliEngineVideoCanvas canvas;
    /* Windows window handle */
    canvas.view = mHWnd;
    mAliRtcEngine.setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
}

HarmonyOS Client

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. Join

Important
  • After a user joins the channel, the system ingests and subscribes to streams based on the parameters that are set before the user joins the channel.

  • By default, the SDK automatically ingests and subscribes to streams to reduce the number of API calls that the client needs to make.

Android

initEngineBeforeJoin();
mAliRtcEngine.joinChannel("Your authentication information", null, null, "testUserName");

iOS

[self initBeforeJoin];
/* The channelId and userId here depend entirely on the values issued by the server; the app does not perceive them. */
[self.engine joinChannel:@"Your authentication information" channelId:nil userId:nil name:@"testUserName" onResultWithUserId:nil];

Windows

initEngineBeforeJoin();
mAliRtcEngine->joinChannel("Your authentication information", null, null, "testUserName");

Harmony Client

this.initEngineBeforeJoin();
this.rtcSdk?.joinChannel("Your authentication information", null, null, "testUserName");

4. Switch roles

Important
  • When a user switches from the streamer role to the viewer role, which is also known as stepping down, the system stops ingesting local audio and video streams. The audio and video streams that are already subscribed to are not affected.

  • When a user switches from the viewer role to the streamer role, which is also known as stepping up, the system ingests local audio and video streams. The audio and video streams that are already subscribed to are not affected.

Android

/* TODO: Set the role based on your business. */
/* Set the interactive role (streamer role). */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* Set the viewing role (viewer role). */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkLive);

iOS

/* TODO: Set the role based on your business. */
/* Set the interactive role (streamer role). */
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* Set the viewing role (viewer role). */
[self.engine setClientRole:AliRtcClientRolelive];

Windows

/* TODO: Set the role based on your business. */
/* Set the interactive role (streamer role). */
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* Set the viewing role (viewer role). */
mAliRtcEngine->SetClientRole(AliEngineClientRoleLive);

HarmonyOS

/* TODO: Set the role based on your business. */
/* Set the interactive role (streamer role). */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleInteractive);
/* Set the viewing role (viewer role). */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleLive);

5. Leave Meeting

Android

mAliRtcEngine.leaveChannel();

iOS

[self.engine leaveChannel];

Windows

mAliRtcEngine->LeaveChannel();

Harmony Client

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;

Effect Display

After you integrate the preceding code, the following result is returned. You can make adjustments as needed.

Android

image.png

iOS

image.png

Windows

image

Other APIs

For more information about API calls, see ApsaraVideo Real-time Communication ARTC SDK.