All Products
Search
Document Center

:Get started with ARTC SDK for Web

Last Updated:Sep 02, 2024

ApsaraVideo Real-time Communication (ARTC) SDK for Web is a set of web-based real-time communication development tools provided by Alibaba Cloud. The SDK allows you to integrate real-time interaction features, such as high-quality audio and video calling and real-time messaging, into a web client. This topic describes how to build your own ARTC application.

Step 1: Create an application

  1. Log on to the ApsaraVideo Live console.

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

  3. Click Create Application.

  4. Enter a custom name in the Instance Name field, select Terms of Service, and then click Buy Now.

  5. After the application is created, refresh the Applications page to view the application.

    Note

    By 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: Obtain the application ID and AppKey

After you create an application, find the application in the application list and click Manage in the Actions column. On the Basic Information tab, obtain the values of Application ID and AppKey.

Step 3: Integrate and use the SDK

  1. Integrate the SDK.

    Use a script

    Import the SDK script into your HTML page.

    <script src="https://g.alicdn.com/apsara-media-box/imp-web-rtc/6.11.8/aliyun-rtc-sdk.js"></script>

    Use npm

    Use npm to install the SDK in your project.

    npm install aliyun-rtc-sdk --save
  2. Initialize the engine.

    // Use one of the following methods.
    // Run the following command if you use npm to integrate the SDK.
    import AliRtcEngine from 'aliyun-rtc-sdk';
    // Run the following command if you use a script to integrate the SDK.
    const AliRtcEngine = window.AliRtcEngine;
    
    // Check the environment.
    const checkResult = await AliRtcEngine.isSupported();
    if (!checkResult.support) {
      // If the environment is unavailable, you are prompted to change or upgrade the browser.
    }
    
    // Create an AliRtcEngine instance, which can be saved as a global variable.
    const aliRtcEngine = AliRtcEngine.getInstance();
    
  3. After you create an AliRtcEngine instance, you need to configure settings to listen to and handle relevant events.

    // Handle the event that the local 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.
    });
    
    // Listen to the event that a remote user gets online.
    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.
    });
    
    // Listen to the event that a remote user gets offline.
    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.
    });
    
    // Listen to the event that the state of subscription to a remote stream changes.
    aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
      // oldState and newState are parameters of AliRtcSubscribeState. The valid values of the parameters are 0 (initialized), 1 (unsubscribed), 2 (subscribing), and 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}.`);
      // 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.
    });
    
    // Listen to the event that the authentication information expires.
    aliRtcEngine.on('authInfoExpired', () => {
      // The callback is triggered when the authentication information expires.
      // You must obtain data such as a token again and then call refreshAuthInfo to update the authentication information.
      aliRtcEngine.refreshAuthInfo({
        userId,
        token,
        timestamp
      });
    });
    
    // Listen to the event that the authentication information is about to expire.
    aliRtcEngine.on('authInfoWillExpire', () => {
      // The callback is triggered 30 seconds before the authentication information expires. After you receive the callback, update the authentication information in a timely manner.
      // If you want to keep staying in the channel, you must obtain data such as a token again and then call joinChannel to join the channel again.
    });
    
  4. Join a channel.

    // Set the channel mode. Valid values: communication and interactive_live.
    aliRtcEngine.setChannelProfile('interactive_live');
    // Specify the user role. This setting takes effect only in the interactive mode.
    // Valid values: interactive and live. The value interactive specifies the streamer role who can ingest and pull streams. The value live specifies the viewer role who can only pull streams.
    aliRtcEngine.setClientRole('interactive');
    
    // Generate authentication information locally or from the server. For more information, see Token-based authentication.
    const appId = 'yourAppId'; // Obtain the application ID from the console.
    const appKey = 'yourAppKey'; // Obtain the AppKey from the console. Do not disclose your AppKey in the production environment.
    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 = 'Test user 1'; // Specify the username.
    const timestamp = Math.floor(Date.now() / 1000) + 3600; // Specify the expiration timestamp. 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 token and nonce parameters are returned by the server.
      await aliRtcEngine.joinChannel({
        channelId,
        userId,
        appId,
        token,
        timestamp,
      }, userName);
      // You succeed in joining the channel. Continue to perform subsequent operations.
    } catch (error) {
      // You fail to join the channel.
    }
    
  5. Start preview and stream ingest. By default, local audio and video data is automatically collected and ingested to Global Realtime Transport Network (GRTN) after you join the channel. You can preview your local stream by performing the following operations.

    1. Add the VIDEO element whose id is localPreviewer to the HTML code.

      <video
        id="localPreviewer"
        muted
        style="display: block;width: 320px;height: 180px;background-color: black;"
      ></video>
    2. Call setLocalViewConfig and 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. The value 1 specifies that the camera stream is previewed. The value 2 specifies that the screen-sharing stream is previewed.
      aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  6. Subscribe to remote audio and video streams. By default, you are automatically subscribed to the audio and video streams of other streamers after you join the channel. Audio streams are automatically played. To play camera streams or screen-sharing streams, call setRemoteViewConfig to configure the settings.

    1. Add the DIV element whose id is remoteVideoContainer as a container to the HTML code.

      <div id="remoteVideoContainer"></div>
    2. If the state of subscription to a remote video stream is changed to subscribed, call setRemoteViewConfig to play the stream. If the state of subscription to a remote video stream is changed to unsubscribed, remove the stream.

      // Save the Video element.
      const remoteVideoElMap = {};
      // Set the remoteVideoContainer element.
      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];
        }
      }
      
      // The following sample code is the same as the description about videoSubscribeStateChanged in Step 2.
      aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
        // oldState and newState are parameters of AliRtcSubscribeState. The valid values of the parameters are 0 (initialized), 1 (unsubscribed), 2 (subscribing), and 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. The value 1 specifies that the camera stream is previewed. The value 2 specifies that the screen-sharing stream is previewed.
          aliRtcEngine.setRemoteViewConfig(video, userId, 1);
        } else if (newState === 1) {
          removeRemoteVideo(userId);
        }
      });
  7. End the process.

    // Stop the local preview.
    await aliRtcEngine.stopPreview();
    // Leave the channel.
    await aliRtcEngine.leaveChannel();
    // Destroy the instance.
    aliRtcEngine.destroy();

Demo

Prerequisites

To try the demo, you need to start an HTTP service in your development environment. If you do not have the npm package that is used to install http-server, run the npm install --global http-server command to install the server globally.

Step 1: Create a directory

Create a folder named demo, and create the quick.html and quick.js files in the folder based on the following directory structure.

- demo
  - quick.html
  - quick.js

Step 2: Edit the quick.html file

Copy the following code to the quick.html file and save the file.

Sample code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>aliyun-rtc-sdk quick start</title>
    <link rel="stylesheet" href="https://g.alicdn.com/code/lib/bootstrap/5.3.0/css/bootstrap.min.css" />
    <style>
      .video {
        display: inline-block;
        width: 320px;
        height: 180px;
        margin-right: 8px;
        margin-bottom: 8px;
        background-color: black;
      }
    </style>
  </head>
  <body class="container p-2">
    <h1>aliyun-rtc-sdk quick start</h1>

    <div class="toast-container position-fixed top-0 end-0 p-3">
      <div id="loginToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
        <div class="toast-header">
          <strong class="me-auto">Logon message</strong>
          <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>
        <div class="toast-body" id="loginToastBody"></div>
      </div>

      <div id="onlineToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
        <div class="toast-header">
          <strong class="me-auto">User getting online</strong>
          <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>
        <div class="toast-body" id="onlineToastBody"></div>
      </div>

      <div id="offlineToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
        <div class="toast-header">
          <strong class="me-auto">User getting offline</strong>
          <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>
        <div class="toast-body" id="offlineToastBody"></div>
      </div>
    </div>

    <div class="row mt-3">
      <div class="col-6">
        <form id="loginForm">
          <div class="form-group mb-2">
            <label for="channelId" class="form-label">Channel ID</label>
            <input class="form-control" id="channelId" />
          </div>
          <div class="form-group mb-2">
            <label for="userId" class="form-label">User ID</label>
            <input class="form-control" id="userId" />
          </div>
          <button id="joinBtn" type="submit" class="btn btn-primary mb-2">Joining the channel</button>
          <button id="leaveBtn" type="button" class="btn btn-secondary mb-2" disabled>Leaving the channel</button>
        </form>
    
        <div class="mt-3">
          <h4>Local preview</h4>
          <video
            id="localPreviewer"
            muted
            class="video"
          ></video>
        </div>
      </div>
      <div class="col-6">
        <h4>Remote user</h4>
        <div id="remoteVideoContainer"></div>
      </div>
    </div>

    <script src="https://g.alicdn.com/code/lib/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://g.alicdn.com/code/lib/bootstrap/5.3.0/js/bootstrap.min.js"></script>
    <script src="https://g.alicdn.com/apsara-media-box/imp-web-rtc/6.11.8/aliyun-rtc-sdk.js"></script>
    <script src="./quick.js"></script>
  </body>
</html>

Step 3: Edit the quick.js file

Copy the following code to the quick.js file, specify the appId and appKey parameters in the code, and save the file.

Sample code

function hex(buffer) {
  const hexCodes = [];
  const view = new DataView(buffer);
  for (let i = 0; i < view.byteLength; i += 4) {
    const value = view.getUint32(i);
    const stringValue = value.toString(16);
    const padding = '00000000';
    const paddedValue = (padding + stringValue).slice(-padding.length);
    hexCodes.push(paddedValue);
  }
  return hexCodes.join('');
}
async function generateToken(appId, appKey, channelId, userId, timestamp) {
  const encoder = new TextEncoder();
  const data = encoder.encode(`${appId}${appKey}${channelId}${userId}${timestamp}`);

  const hash = await crypto.subtle.digest('SHA-256', data);
  return hex(hash);
}

function showToast(baseId, message) {
  $(`#${baseId}Body`).text(message);
  const toast = new bootstrap.Toast($(`#${baseId}`));

  toast.show();
}

// Specify your application ID and AppKey.
const appId = '';
const appKey = '';
AliRtcEngine.setLogLevel(0);
let aliRtcEngine;
const remoteVideoElMap = {};
const remoteVideoContainer = document.querySelector('#remoteVideoContainer');

function removeRemoteVideo(userId, type = 'camera') {
  const vid = `${type}_${userId}`;
  const el = remoteVideoElMap[vid];
  if (el) {
    aliRtcEngine.setRemoteViewConfig(null, userId, type === 'camera' ?  1: 2);
    el.pause();
    remoteVideoContainer.removeChild(el);
    delete remoteVideoElMap[vid];
  }
}

function listenEvents() {
  if (!aliRtcEngine) {
    return;
  }
  // Listen to the event that a remote user gets online.
  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.
    showToast('onlineToast', `The user ${userId} is online.`);
  });

  // Listen to the event that a remote user gets offline.
  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.
    showToast('offlineToast', `The user ${userId} is offline.`);
    removeRemoteVideo(userId, 'camera');
    removeRemoteVideo(userId, 'screen');
  });

  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.
    showToast('loginToast', `You have left the channel. Reason: ${code}.`);
  });

  aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState and newState are parameters of AliRtcSubscribeState. The valid values of the parameters are 0 (initialized), 1 (unsubscribed), 2 (subscribing), and 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}.`);
    const vid = `camera_${userId}`;
    // The following sample code provides a handling example.
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = 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. The value 1 specifies that the camera stream is previewed. The value 2 specifies that the screen-sharing stream is previewed.
      aliRtcEngine.setRemoteViewConfig(video, userId, 1);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'camera');
    }
  });

  aliRtcEngine.on('screenShareSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState and newState are parameters of AliRtcSubscribeState. The valid values of the parameters are 0 (initialized), 1 (unsubscribed), 2 (subscribing), and 3 (subscribed).
    // interval specifies the time elapsed for the change between two states, in milliseconds.
    console.log(`The state of subscription to the screen-sharing stream of the remote user ${userId} in the channel ${channelId} is changed from ${oldState} to ${newState}`);
    const vid = `screen_${userId}`;
    // The following sample code provides a handling example.    
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = 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. The value 1 specifies that the camera stream is previewed. The value 2 specifies that the screen-sharing stream is previewed.
      aliRtcEngine.setRemoteViewConfig(video, userId, 2);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'screen');
    }
  });
}

$('#loginForm').submit(async e => {
  // Prevent the form from being submitted by default.
  e.preventDefault();
  const channelId = $('#channelId').val();
  const userId = $('#userId').val();
  const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;

  if (!channelId || !userId) {
    showToast('loginToast', 'The data is incomplete.');
    return;
  }

  aliRtcEngine = AliRtcEngine.getInstance();
  listenEvents();

  try {
    const token = await generateToken(appId, appKey, channelId, userId, timestamp);
    // Set the mode of the channel. Valid values: communication and interactive_live.
    aliRtcEngine.setChannelProfile('communication');
    // Specify the user role. This setting takes effect only in the interactive mode.
    // Valid values: interactive and live. The value interactive specifies the streamer role who can ingest and pull streams. The value live specifies the viewer role who can only pull streams.
    // aliRtcEngine.setClientRole('interactive');
    // Join the channel. The token and nonce parameters are returned by the server.
    await aliRtcEngine.joinChannel(
      {
        channelId,
        userId,
        appId,
        token,
        timestamp,
      },
      userId
    );
    showToast('loginToast', 'You succeed in joining the channel.');
    $('#joinBtn').prop('disabled', true);
    $('#leaveBtn').prop('disabled', false);

    // Start preview.
    aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  } catch (error) {
    console.log('Failed to join the channel.', error);
    showToast('loginToast', 'You fail to join the channel.');
  }
});

$('#leaveBtn').click(async () => {
  Object.keys(remoteVideoElMap).forEach(vid => {
    const arr = vid.split('_');
    removeRemoteVideo(arr[1], arr[0]);
  });
  // Stop the local preview.
  await aliRtcEngine.stopPreview();
  // Leave the channel.
  await aliRtcEngine.leaveChannel();
  // Destroy the instance.
  aliRtcEngine.destroy();
  aliRtcEngine = undefined;
  $('#joinBtn').prop('disabled', false);
  $('#leaveBtn').prop('disabled', true);
  showToast('loginToast', 'You have left the channel.');
});

Step 4: Run the demo

  1. In the terminal, open the demo folder and run http-server -p 8080 to start an HTTP service.

  2. Create a tab in the browser. On the tab, access localhost:8080/quick.html, fill in your channel ID and user ID, and click the Join Channel button.

  3. Create another tab in the browser. On the tab, access localhost:8080/quick.html, fill in the same channel ID and another user ID, and click the Join Channel button.

  4. Verify that you are automatically subscribed to the media stream of the remote user.