Add real-time audio and video communication to your web application with the Alibaba Cloud ARTC Web SDK. This guide walks you through creating an ARTC application, integrating the SDK, and building a working video call.
Step 1: Create an application
Log on to the ApsaraVideo Live console.
In the navigation pane on the left, click .
Click Create Application.
Enter a custom Instance Name, read the Terms of Service, and then click Buy Now.
After a success message appears, refresh the Applications page to view your new ARTC application.
NoteCreating an application is free. You are charged on a pay-as-you-go basis for actual usage. For billing information, see Billing for audio/video communication.
Step 2: Get the AppID and AppKey
After you create the application, find it in the list. In the Actions column, click Manage to go to the Basic Information page. On this page, you can find the Application ID and AppKey. Save these values for later steps.

Step 3: Integrate the SDK
Integrate the SDK.
Use a script
Add the following script to your HTML file:
<script src="https://g.alicdn.com/apsara-media-box/imp-web-rtc/7.1.9/aliyun-rtc-sdk.js"></script>Use npm
Use npm to install the SDK in your project.
npm install aliyun-rtc-sdk --saveInitialize the engine.
// Use one of the following methods. // Run the following command if you installed via npm. import AliRtcEngine from 'aliyun-rtc-sdk'; // Run the following command if you used a script. const AliRtcEngine = window.AliRtcEngine; // Check browser compatibility. const checkResult = await AliRtcEngine.isSupported(); if (!checkResult.support) { // The browser does not support WebRTC. Change or upgrade the browser. } // Create an AliRtcEngine instance, which can be saved as a global variable. const aliRtcEngine = AliRtcEngine.getInstance();Listen for and handle related events.
// Triggered when the current user leaves the channel. aliRtcEngine.on('bye', (code) => { // code indicates the reason for leaving the channel. For more information, see the API reference. console.log(`bye, code=${code}`); // Configure your handling logic, such as exiting the calling page. }); // Triggered when a remote user joins the channel. aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => { console.log(`The user ${userId} has joined the channel. Time consumed: ${elapsed} seconds.`); // Configure your handling logic, such as displaying the module of the remote user. }); // Triggered when a remote user leaves the channel. aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => { // reason indicates the reason why the remote user gets offline. For more information, see the API reference. console.log(`The user ${userId} has left the channel. Reason: ${reason}.`); // Configure your handling logic, such as destroying the module of the remote user. }); // Triggered when the subscription state of a remote video stream changes. aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => { // oldState and newState are parameters of AliRtcSubscribeState. The valid values are 0 (initialized), 1 (unsubscribed), 2 (subscribing), and 3 (subscribed). // interval indicates the time elapsed for the change between two states, in milliseconds. console.log(`The state of subscription to the remote user ${userId} in the channel ${channelId} is changed from ${oldState} to ${newState}.`); // Configure the handling logic for the remote stream. // Call setRemoteViewConfig to play the remote stream if the value of newState changes to 3. // Stop the playback if the value of newState changes to 1. }); // Triggered when authentication information expires. aliRtcEngine.on('authInfoExpired', () => { // The authentication information has expired. // Obtain a new token from your server and then call refreshAuthInfo to update the authentication information. aliRtcEngine.refreshAuthInfo({ userId, token, timestamp }); }); // Triggered 30 seconds before authentication information expires. aliRtcEngine.on('authInfoWillExpire', () => { // After receiving the notification, update the authentication information in a timely manner. // To stay in the session, obtain a new token from your server and then call joinChannel to join the channel again. });(Optional) Set the channel mode. The default mode is communication mode. For more information, see Set the channel mode and user role.
// Set the channel mode. Valid arguments: communication (the communication mode) and interactive_live (the interactive mode). aliRtcEngine.setChannelProfile('interactive_live'); // Set the user role. The method is valid only in the interactive mode. // Valid arguments: interactive (can publish and subscribe) and live (subscribe only). aliRtcEngine.setClientRole('interactive');Generate a token and call joinChannel to join a channel. For details about token calculation, see Implement token-based authentication.
Join with a single parameter (recommended for production):
In this approach, your server generates a Base64-encoded token. The client retrieves it through an authenticated API call.
const userName = 'User 1'; // Custom user name. The name supports Chinese characters. try { // Implement fetchToken() to retrieve the Base64-encoded token from your server. const base64Token = await fetchToken(); await aliRtcEngine.joinChannel(base64Token, userName); // Continue to perform subsequent operations after joining the channel. } catch (error) { // Handle potential errors if you fail to join the channel. }Join with multiple parameters (for development and testing):
// Generate a token on the server side or on the on-premises machine. // Note: For your data security, never expose the token generation logic and AppKey in client-side code. const appId = 'yourAppId'; // Enter the application ID obtained from Step 2. const appKey = 'yourAppKey'; // Enter the AppKey obtained from Step 2. Note: Do not expose your AppKey in the production environments. const channelId = 'AliRtcDemo'; // Specify the channel ID. The ID can contain only letters and digits. const userId = 'test1'; // Specify the user ID. The ID can contain only letters and digits. const userName = 'User 1'; // Specify the username. The name supports Chinese characters. const timestamp = Math.floor(Date.now() / 1000) + 3600; // Specify the expiration time of the token. For example, a value of 3600 specifies that the token expires an hour after it is generated. try { const token = await generateToken(appId, appKey, channelId, userId, timestamp); // Join the channel. The parameters, token, and nonce are generally returned from the server. // The channelId, userId, appId, and timestamp parameters must be the same as those used to generate the token. await aliRtcEngine.joinChannel({ channelId, userId, appId, token, timestamp, }, userName); // Continue to perform subsequent operations after joining the channel. } catch (error) { // Handle potential errors if you fail to join the channel. }
By default, after joining a channel, the SDK automatically captures local audio and video and publishes the stream to Global Realtime Transport Network (GRTN). To display a preview of the local video feed, follow these steps:
Create a
<video>element in your HTML file to serve as the container for the local preview. ItsidislocalPreviewer.<video id="localPreviewer" muted style="display: block;width: 320px;height: 180px;background-color: black;" ></video>Call
setLocalViewConfigand pass in the element ID to start preview.// For the first parameter, pass in HTMLVideoElement or specify the element ID. If you set the value to null, the preview is stopped. // Set the value of the second parameter to 1 or 2. 1: the camera stream. 2: the screen sharing stream. aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
By default, the SDK automatically subscribes to the audio and video streams of other host users in the channel. While remote audio will begin playing automatically, you must explicitly render the video streams (both camera and screen sharing) using the
setRemoteViewConfigmethod.In your HTML, create a
<div>element to act as a container. This container will hold the dynamically created<video>elements for each remote user.<div id="remoteVideoContainer"></div>The core logic for managing remote videos involves listening for the
videoSubscribeStateChangedevent. This event fires whenever the subscription status of a remote user's video changes. The following code demonstrates how to dynamically create and remove video elements based on these events.// Map to store remote user IDs to their corresponding <video> elements const remoteVideoElMap = {}; // Get the container element for remote videos const remoteVideoContainer = document.querySelector('#remoteVideoContainer'); function removeRemoteVideo(userId) { const el = remoteVideoElMap[userId]; if (el) { aliRtcEngine.setRemoteViewConfig(null, userId, 1); el.pause(); remoteVideoContainer.removeChild(el); delete remoteVideoElMap[userId]; } } // Listen for changes in remote video subscription status aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => { // oldState and newState are of type AliRtcSubscribeState. 0: initializing, 1: unsubscribed, 2: subscribing, 3: subscribed // interval specifies the time elapsed for the change between two states, in milliseconds. console.log(`The state of subscription to the remote user ${userId} in the channel ${channelId} is changed from ${oldState} to ${newState}.`); // The following sample code provides a handling example. if (newState === 3) { const video = document.createElement('video'); video.autoplay = true; video.setAttribute('style', 'display: block;width: 320px;height: 180px;background-color: black;'); remoteVideoElMap[userId] = video; remoteVideoContainer.appendChild(video); // For the first parameter, pass in HTMLVideoElement. // For the second parameter, specify the ID of the remote user. // Set the value of the third parameter to 1 or 2. 1: the camera stream. 2: the screen sharing stream. aliRtcEngine.setRemoteViewConfig(video, userId, 1); } else if (newState === 1) { removeRemoteVideo(userId); } });
Clean up.
// Stop the local preview. await aliRtcEngine.stopPreview(); // Leave the channel. await aliRtcEngine.leaveChannel(); // Destroy the instance. aliRtcEngine.destroy();
Demo
The demo generates tokens (generateToken) on the client side using your AppKey. This is for local testing only. Never expose your AppKey in client-side code in a production environment. We recommend that you generate tokens on your server and retrieve them on the frontend by making an authenticated API call.
Prerequisite
Install the http-server package if you haven't already:
npm install --global http-serverStep 1: Create a directory
Create the following file structure:
- demo
- quick.html
- quick.jsStep 2: Edit quick.html
Copy the following code to the quick.html file:
Step 3: Edit quick.js
Copy the following code to the quick.js file, specify the appId and appKey parameters in the code, and save the file.
Step 4: Run the demo
In the terminal, navigate to the demo folder and run
http-server -p 8080to start the HTTP service.Open
localhost:8080/quick.htmlin the browser, enter a channel ID and user ID, then click Join Channel.Create another tab in the browser. Open
localhost:8080/quick.html, enter the same channel ID and another user ID, and click Join Channel.Both tabs show the video feed from the other user. Toast notifications confirm when each user joins.