RTC quick start

Updated at:

This guide explains how to create an RTC application by using Alibaba Cloud resources.

Procedure

Actions

Description

Step 1: Create an application

Create an ARTC application in the ApsaraVideo Live console. After creating the application, obtain its App ID and App Key.

Note
  • The instance name supports both Chinese and English.

  • By default, creating an application is free. You are billed for your actual usage.

Step 2: Server-side integration

After obtaining the App ID and App Key, copy the provided authentication code for your programming language into your server-side application.

Step 3: SDK integration

After completing the server-side configuration, use CocoaPods (for iOS) or Maven (for Android) to integrate the SDK.

Step 1: Create an application

  1. Log in to the ApsaraVideo Live console.

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

  3. Click Create Application.

  4. Enter a custom application name, select the service agreement checkbox, and click Buy Now.

  5. Once the application is created, refresh the Application Management page to view your new ApsaraVideo for RTC application.

    Note

    Creating an application does not incur charges by default. Billing is pay-as-you-go and based on actual usage. For more information, see RTC Pricing.

Step 2: Server integration

  1. Integrate the authentication code provided by Alibaba Cloud into your server-side environment. For example, to join a channel using Java with a single parameter, see token authentication.

  2. Provide a server-side API for your mobile app to call.

Step 3: SDK integration

Based on your business requirements, you can select the interactive mode for interactive entertainment scenarios or the communication mode for one-to-one or one-to-many broadcasting. Selecting the correct mode ensures a smooth user experience and efficient use of network resources.

Mode

Stream pushing

Stream pulling

Description

Interactive mode

  • Role-based. Only users assigned the host role can push streams.

  • Participants can switch roles at any time during the session.

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

  • In interactive mode, the audience receives real-time notifications when a host joins or leaves a meeting or starts pushing a live stream. Conversely, the host does not receive notifications about audience activities, which ensures an uninterrupted stream.

  • In interactive mode, the host is responsible for live interaction, while the audience primarily receives content. If you are unsure whether audience interaction will be required in the future, use interactive mode by default. Its flexibility lets you adjust user role permissions for different interaction requirements.

Communication mode

No role restrictions. All participants have permission to push streams.

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

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

  • Although this mode does not distinguish between user roles, all participants effectively have the same permissions as a host in interactive mode. This simplifies operations, allowing users to achieve the desired functionality with fewer API calls.

1. Project configuration

Android

We recommend using a Maven repository to add the required dependencies.

  1. In your root-level build.gradle file, add the Maven repository URL.

    allprojects {
        repositories {
            google()
            jcenter()
            // Add the Maven repository for RTC
            maven {
                url "https://maven.aliyun.com/nexus/content/repositories/releases"
            }
        }
    }
  2. In your project's app/build.gradle file, add the following dependency.

    // Add the dependency for the Real-Time Communication SDK (RTC SDK) 
    implementation 'com.aliyun.aio:AliVCSDK_ARTC:${latest version}'
  3. In your app/src/main/AndroidManifest.xml file, add the following code to request 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

    You must request the following permissions at runtime:

    • Manifest.permission.CAMERA

    • Manifest.permission.WRITE_EXTERNAL_STORAGE

    • Manifest.permission.RECORD_AUDIO

    • Manifest.permission.READ_EXTERNAL_STORAGE

    If your app targets Android 12 (API level 31) or higher, you must also request the following permission at runtime:

    • 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

We recommend using CocoaPods to integrate the SDK.

  1. Run the following command in a terminal to install CocoaPods.

    Important

    Before using CocoaPods, ensure Ruby is installed on your Mac.

    sudo gem install cocoapods
  2. Navigate to your project directory and run the following command 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 a terminal to update CocoaPods dependencies for your project. After the command completes, CocoaPods generates an .xcworkspace file that includes the integrated SDK. From now on, use this .xcworkspace file to open your project in Xcode.

    pod update
  5. Add permission requests.

    Important

    You must add permissions for the microphone and camera.

    1. In the Info.plist file, add the Privacy - Camera Usage Description and Privacy - Microphone Usage Description keys to provide usage descriptions for camera and microphone access.

    2. Enable audio background mode. To do this, select Audio, AirPlay, and Picture in Picture.

      In your Xcode project settings, on the Signing & Capabilities tab, expand the Background Modes section to make your selection.

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

Windows

We recommend using Visual Studio 2015 to integrate the SDK.

  1. Add the runtime library include path. Right-click the Tutorial project, select Properties (or press Alt+Enter) to open the project's Property Pages. Navigate to Configuration Properties > C/C++ > General and set Additional Include Directories to $(ProjectDir)..\..\..\AliRTCSdk\WindowsSDK\ali.

  2. Add the runtime library path. In the project's Property Pages, navigate to Linker > General and add the runtime library's lib path, such as $(ProjectDir)..\CrashDump\lib\x64\debug, to the Additional Library Directories field.

Linux

Prerequisites for Java

Prerequisites for Python

Prerequisites for C++

Prerequisites for Go

HarmonyOS

  1. Prerequisites

    Before integrating the Alibaba Cloud Audio and Video SDK, ensure your development environment meets the following requirements:

    • Contact your Huawei account team, sign a cooperation plan, and enable specific permissions to obtain DevEco Studio 5.0.3.900 Release or later.

    • The HarmonyOS NEXT SDK for API Version 12 or later.

    • A HarmonyOS device that supports audio and video, runs HarmonyOS NEXT 5.0.0.102 (for API Version 12) or later, and has the "Allow debugging" option enabled.

    • If you need to perform on-device debugging, see the HarmonyOS official documentation for configuration.

    • The HarmonyOS device is connected to the internet.

    • A registered HUAWEI ID with completed identity verification.

  2. Project configuration
    1. Manual import

      Download the AliVCSDK_ARTC-6.11.0-Beta.har package and place it in your project's libs directory. Then, configure the dependency in your project:

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

      Configure the dependency in your 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 engine and callbacks

Important

The SDK uses an internal retry mechanism to automatically recover from exceptions. For errors the SDK cannot resolve, it notifies your application through API callbacks.

Cause

Callback and parameters

Solution

Description

Authentication failure

The result parameter in the onJoinChannelResult callback returns AliRtcErrJoinBadToken.

Check if the token is valid.

If authentication fails when your application calls an API, the SDK returns an authentication error in the corresponding callback.

Authentication token is about to expire

onWillAuthInfoExpire

When this callback is triggered, get a new authentication token and call refreshAuthInfo.

This callback warns that the token is about to expire, allowing your application to refresh it proactively.

Authentication token has expired

onAuthInfoExpired

Rejoin the channel.

If the token expires, the SDK triggers this callback. You must then rejoin the channel with a new token.

Network connection exception

The onConnectionStatusChange callback returns the status AliRtcConnectionStatusFailed.

Rejoin the channel.

The SDK attempts to automatically recover from network disconnections. If a disconnection exceeds the timeout threshold, the SDK drops the connection. Your application should then check the network status and prompt the user to rejoin the channel.

Kicked offline

onBye

  • AliRtcOnByeUserReplaced: Another user with the same user ID has joined. Check for duplicate user IDs.

  • AliRtcOnByeBeKickedOut: The user was removed by the application server. Rejoin the channel.

  • AliRtcOnByeChannelTerminated: The channel was destroyed. Rejoin the channel.

Administrators can remove participants through the Real-time Communication service.

Local device exception

onLocalDeviceException

Check device permissions and hardware status.

The Real-time Communication service supports device detection and diagnostics. When a local device exception occurs, the service notifies the client through a callback. If the SDK cannot resolve the issue, your application must check the device status.

Android

private void createEngine() {
    mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext());
    mAliRtcEngine.setRtcEngineEventListener(new AliRtcEngineEventListener() {
        /* Notification of the connection status between the SDK and 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: Required. We recommend notifying the user. This callback is triggered only after the SDK's internal recovery strategies have failed. */
            } else {
                /* TODO: Optional. Add business logic, typically for data statistics or UI updates. */
            }
        }
        /* The SDK attempts to handle local device exceptions. */
        @Override
        public void OnLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType aliRtcEngineLocalDeviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType aliRtcEngineLocalDeviceExceptionType, String s) {
            super.OnLocalDeviceException(aliRtcEngineLocalDeviceType, aliRtcEngineLocalDeviceExceptionType, s);
            /* TODO: Required. We recommend notifying the user of the error. This callback is triggered only after the SDK's internal recovery strategies have failed. */
        }
        @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 updates. */
            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() {
        /* This callback is triggered 30 seconds before the authentication token expires. You must refresh the token. */
        @Override
        public void onAuthInfoWillExpire() {
            super.onAuthInfoWillExpire();
            /* TODO: Required. Your application must retrieve a new authentication token for the current channel and user, and then call refreshAuthInfo. */
        }
        /* You must handle this callback, as it is triggered when the application server kicks out a user. */
        @Override
        public void onBye(int code) {
            super.onBye(code);
            /* TODO: Recommended. Handle this event according to your application's logic. */
        }
        @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 = @"";
        /* Create the engine and pass the delegate. */
        _engine = [AliRtcEngine sharedInstance:self extras:extras];
    }
    return _engine;
}
#pragma mark - "Delegates of engine"
/* This callback is triggered 30 seconds before the authentication token expires. You must refresh the token. */
- (void)onAuthInfoWillExpire{
    /* TODO: Required. Your application must retrieve a new authentication token for the current channel and user, and then call refreshAuthInfo. */
}
/* Notification of the connection status between the SDK and the server. You must handle connection failures. */
- (void)onConnectionStatusChange:(AliRtcConnectionStatus)status reason:(AliRtcConnectionStatusChangeReason)reason {
    if (status == AliRtcConnectionStatusFailed) {
        /* TODO: Required. We recommend notifying the user. This callback is triggered only after the SDK's internal recovery strategies have failed. */
    } else {
        /* TODO: Optional. Add business logic, typically for data statistics or UI updates. */
    }
}
/* The SDK attempts to handle local device exceptions. */
- (void)onLocalDeviceException:(AliRtcLocalDeviceType)deviceType exceptionType:(AliRtcLocalDeviceExceptionType)exceptionType message:(NSString *_Nullable)msg {
    /* TODO: Required. We recommend notifying the user of the error. This callback is triggered only after the SDK's internal recovery strategies have failed. */
}
/* You must handle this callback, as it is triggered when the application server kicks out a user. */
- (void)onBye:(int)code {
    /* TODO: Recommended. Handle this event according to your application's logic. */
}
/* Notification for remote stream availability. In auto-subscribe mode, use this to manage the UI before the first frame is rendered. */
- (void)onRemoteTrackAvailableNotify:(NSString *_Nonnull)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
    /* TODO: Required. Set a video rendering view 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 view. Note that the user might have already left the channel. */
            [self.engine setRemoteViewConfig:nil uid:uid forTrack:AliRtcVideoTrackCamera];
        }
    });
}
- (void)onRemoteUserOffLineNotify:(NSString *)uid offlineReason:(AliRtcUserOfflineReason)reason {
    dispatch_async(dispatch_get_main_queue(), ^{
        /* Also clear the remote user's rendering view here. */
        [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 updates. */
}
- (void)onLeaveChannelResult:(int)result stats:(AliRtcStats)stats {
    /* TODO: Optional. Add business logic, typically for data statistics or UI updates. */
}

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. We recommend notifying the user. This callback is triggered only after the SDK's internal recovery strategies have failed. */
        } else {
            /* TODO: Optional. Add business logic, typically for data statistics or UI updates. */
        }
    };
    virtual void OnLocalDeviceException(AliEngineLocalDeviceType deviceType, AliEngineLocalDeviceExceptionType exceptionType, const char* msg) override {
        /* TODO: Required. We recommend notifying the user of the error. This callback is triggered only after the SDK's internal recovery strategies have failed. */
    };
    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 updates. */
    };
    virtual void OnLeaveChannelResult(int result, AliEngineStats stats) override {
    };
    virtual void OnAuthInfoWillExpire() override {
        /* TODO: Required. Your application must retrieve a new authentication token for the current channel and user, and then call refreshAuthInfo. */
    };
    virtual void OnBye(int code) override {
        /* Recommended: Handle this event, which can be triggered if a user is kicked by the server. */
    };
    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);
}

Linux

Initialize the Java SDK

Initialize the Python SDK

Initialize the C++ SDK

Initialize the Go SDK

HarmonyOS

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

2. Pre-join parameters

Important
  • In interactive mode, if the user role is set to host, the SDK automatically publishes local audio and video streams and subscribes to streams from other hosts by default.

  • In interactive mode with the audience role, the SDK does not publish local audio and video streams but subscribes to streams from other hosts.

  • By default, the SDK automatically publishes and subscribes to streams. You can disable this behavior.

Android

    private void initEngineBeforeJoin() {
        /* Optional: Configure parameters 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: Set up a camera preview. The stream will be published even if this is 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: Configure parameters before joining the channel. */
    [self.engine setChannelProfile:AliRtcInteractivelive];
    [self.engine setClientRole:AliRtcClientRoleInteractive];
    /* Set audio properties. */
    [self.engine setAudioProfile:AliRtcEngineStereoHighQualityMode audio_scene:AliRtcSceneMusicMode];
    /* Optional: Set up a camera preview. The stream will be published even if this is 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: Configure parameters before joining the channel. */
    mAliRtcEngine->SetChannelProfile(AliEngineInteractiveLive);
    mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
    /* Set audio properties. */
    mAliRtcEngine->SetAudioProfile(AliEngineBasicQualityMode, AliEngineSceneMusicMode);
    /* Optional: Set up a camera preview. The stream will be published even if this is not set. */
    AliEngineVideoCanvas canvas;
    /* Windows window handle */
    canvas.view = mHWnd;
    mAliRtcEngine.setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
}

Linux

Set Java parameters

Set Python parameters

Set C++ parameters

Set Go parameters

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

Important
  • After you join a channel, streams are published and subscribed to based on the pre-join configurations.

  • By default, the SDK automatically publishes and subscribes to streams, minimizing the number of required client-side API calls.

Android

initEngineBeforeJoin();
mAliRtcEngine.joinChannel("", null, null, "testUserName");

iOS

[self initBeforeJoin];
/* The channelId and userId are determined by your server; the client application should treat these values as opaque. */
[self.engine joinChannel:@"" channelId:nil userId:nil name:@"testUserName" onResultWithUserId:nil];

Windows

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

Linux

Join a channel with Java

Join a channel with Python

Join a channel with C++

Join a channel with Go

HarmonyOS

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

4. Switch role

Important
  • When a user switches from the host role to the audience role, the SDK stops publishing local audio and video streams. This does not affect subscribed streams.

  • When a user switches from the audience role to the host role, the SDK starts publishing local audio and video streams. This does not affect subscribed streams.

Android

/* TODO: Set the role based on your application logic. */
/* Set the user role to host. */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* Set the user role to audience. */
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkLive);

iOS

/* TODO: Set the role based on your application logic. */
/* Set the user role to host. */
[self.engine setClientRole:AliRtcClientRoleInteractive];
/* Set the user role to audience. */
[self.engine setClientRole:AliRtcClientRolelive];

Windows

/* TODO: Set the role based on your application logic. */
/* Set the user role to host. */
mAliRtcEngine->SetClientRole(AliEngineClientRoleInteractive);
/* Set the user role to audience. */
mAliRtcEngine->SetClientRole(AliEngineClientRoleLive);

Linux

Switch role with Java

Switch role with Python

Switch role with C++

Switch role with Go

HarmonyOS

/* TODO: Set the role based on your application logic. */
/* Set the user role to host. */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleInteractive);
/* Set the user role to audience. */
this.rtcSdk?.setClientRole(AliRtcClientRole.AliEngineClientRoleLive);

5. Leave the channel

Android

mAliRtcEngine.leaveChannel();

iOS

[self.engine leaveChannel];

Windows

mAliRtcEngine->LeaveChannel();

Linux

Leave the channel with Java

Leave the channel with Python

Leave the channel with C++

Leave the channel with Go

HarmonyOS

this.rtcSdk?.leaveChannel();

6. Destroy the engine

Android

mAliRtcEngine.destroy();
mAliRtcEngine = null;

iOS

[AliRtcEngine destroy];

Windows

mAliRtcEngine->Destroy();
mAliRtcEngine = nullptr;

Linux

Destroy the engine with Java

Destroy the engine with Python

Destroy the engine with C++

Destroy the engine with Go

HarmonyOS

AliRtcEngine.destroyInstance();
this.rtcSdk? = null;

Demonstration

After integrating the code, your result will resemble the examples below. You can adjust the implementation to meet your business requirements.

Android

image.png

iOS

image.png

Windows

Once the video call starts, the remote video appears in the upper-left corner and the local video in the bottom center. A control bar for the call is on the right.

Other APIs

For detailed API information, see the Real-time Communication ARTC SDK documentation.