Tous les produits
Search
Centre de documentation

ApsaraVideo Live:Prise en main du SDK Web ARTC

Dernière mise à jour :Aug 19, 2026

Le SDK Web ApsaraVideo Real-time Communication (ARTC) est une boîte à outils fournie par Alibaba Cloud pour le développement d'applications web de communication en temps réel. Il vous permet d'intégrer rapidement des fonctionnalités de haute qualité, telles que les appels audio/vidéo et la messagerie instantanée, dans vos applications web. Ce guide vous explique comment créer rapidement votre première application ARTC.

Étape 1 : Créer une application

  1. Connectez-vous à la console ApsaraVideo Live.

  2. Dans le volet de navigation de gauche, accédez à Live + > ApsaraVideo Real-time Communication > Applications.

  3. Cliquez sur Create Application.

  4. Saisissez un nom d'instance personnalisé, cochez la case Terms of Service, puis cliquez sur Create Now.

  5. Une fois le message de succès affiché, actualisez la page Applications pour consulter votre nouvelle application ApsaraVideo Real-time Communication.

    Remarque

    La création d'une application est gratuite. La facturation s'effectue selon le modèle de paiement à l'utilisation, en fonction de votre consommation réelle. Pour plus d'informations, consultez la rubrique Facturation des appels audio et vidéo.

Étape 2 : Obtenir l'ID d'application et l'AppKey

Après avoir créé l'application, localisez-la dans la liste des applications. Dans la colonne Actions, cliquez sur Manage pour ouvrir la page Basic Information. Sur cette page, repérez l'Application ID et l'AppKey.

Étape 3 : Intégrer le SDK

Le SDK Web ARTC est un SDK JavaScript standard compatible avec tous les frameworks frontaux courants, notamment Vue 2, Vue 3 et React. Les exemples de code fournis dans cette rubrique sont rédigés en JavaScript natif. Si vous développez avec un framework tel que Vue 2, vous devez adapter vous-même les exemples JavaScript officiels aux conventions de votre framework (par exemple, la gestion du cycle de vie et l'encapsulation des composants). Des exemples de code spécifiques aux frameworks ne sont pas disponibles pour le moment.

  1. Intégrez le SDK.

    Script

    Dans votre page HTML, incluez le script du SDK.

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

    NPM

    Dans votre projet, exécutez la commande suivante pour installer le SDK.

    npm install aliyun-rtc-sdk --save
  2. Initialisez le moteur.

    // Choose one of the following two import methods.
    // Use this if you are importing from an npm package.
    import AliRtcEngine from 'aliyun-rtc-sdk';
    // Use this if you are including the SDK with a script tag.
    const AliRtcEngine = window.AliRtcEngine;
    // Check browser compatibility.
    const checkResult = await AliRtcEngine.isSupported();
    if (!checkResult.support) {
      // The current environment is not supported. Prompt the user to switch to or upgrade their browser.
    }
    // Create an engine instance. You can save it as a global variable.
    const aliRtcEngine = AliRtcEngine.getInstance();
    
  3. Après avoir créé l'instance AliRtcEngine, écoutez et gérez les événements pertinents.

    // Fired when the local user leaves the channel.
    aliRtcEngine.on('bye', (code) => {
      // `code` is a reason code. For details, see the API reference.
      console.log(`bye, code=${code}`);
      // Handle your business logic here, such as exiting the call page.
    });
    // Fired when a remote user comes online.
    aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => {
      console.log(`User ${userId} joined the channel in ${elapsed} seconds.`);
      // Handle your business logic here, such as displaying the UI module for this user.
    });
    // Fired when a remote user goes offline.
    aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => {
      // `reason` is a reason code. For details, see the API reference.
      console.log(`User ${userId} left the channel. Reason code: ${reason}`);
      // Handle your business logic here, such as destroying the UI module for this user.
    });
    // Fired when the subscription state of a remote stream changes.
    aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
      // 'oldState' and 'newState' are AliRtcSubscribeState values.
      // Values: 0 (initialized), 1 (unsubscribed), 2 (subscribing), 3 (subscribed).
      // `interval` is the time between state changes, in milliseconds.
      console.log(`Subscription state of remote user ${userId} in channel ${channelId} changed from ${oldState} to ${newState}.`);
      // Handle the logic for viewing the remote stream here.
      // When `newState` becomes 3, you can play the remote stream by calling setRemoteViewConfig.
      // When `newState` becomes 1, you can stop the playback.
    });
    // Fired when the authentication information expires.
    aliRtcEngine.on('authInfoExpired', () => {
      // This callback indicates that the authentication information has expired.
      // Get a new token and other data, then call the refreshAuthInfo method to update the authentication data.
      aliRtcEngine.refreshAuthInfo({
        userId,
        token,
        timestamp
      });
    });
    // Fired when the authentication information is about to expire.
    aliRtcEngine.on('authInfoWillExpire', () => {
      // This callback is fired 30 seconds before expiration. You should update the authentication information promptly.
      // To stay in the session, get a new token and other data, and call joinChannel to rejoin the channel.
    });
    
  4. (Facultatif) Définissez le mode de canal. Le mode par défaut est le mode de communication. Pour plus d'informations, consultez la rubrique Définir le mode de canal et le rôle utilisateur.

    // Set the channel mode. Valid values: 'communication' (communication mode), 'interactive_live' (interactive mode).
    aliRtcEngine.setChannelProfile('interactive_live');
    // Set the user role. This method is effective only in interactive mode.
    // Valid values: 'interactive' (streamer, can publish and subscribe to streams), 'live' (viewer, can only subscribe to streams).
    aliRtcEngine.setClientRole('interactive');
  5. Rejoignez un canal. Pour savoir comment générer un jeton, consultez la rubrique authentification basée sur un jeton. Vous pouvez choisir de rejoindre le canal avec un seul paramètre ou plusieurs paramètres selon vos besoins.

    • Rejoindre avec un seul paramètre

      const userName = 'Test User 1'; // You can change this to your username. Chinese characters are supported.
      try {
        // You need to implement fetchToken to get the Base64-encoded token from your server.
        const base64Token = await fetchToken();
        await aliRtcEngine.joinChannel(base64Token, userName);
        // Joined the channel successfully. Proceed with other operations.
      } catch (error) {
        // Failed to join the channel.
      }
    • Rejoindre avec plusieurs paramètres

      // Generate authentication information on your server or locally by following the token-based authentication guide.
      // IMPORTANT: For data security, never publish the token calculation logic that includes your AppKey to end users.
      const appId = 'yourAppId'; // Get this from the console.
      const appKey = 'yourAppKey'; // Get this from the console. Do not expose your AppKey in a production environment.
      const channelId = 'AliRtcDemo'; // You can change this to your channel ID. Only letters and digits are supported.
      const userId = 'test1'; // You can change this to your user ID. Only letters and digits are supported.
      const userName = 'Test User 1'; // You can change this to your username. Chinese characters are supported.
      const timestamp = Math.floor(Date.now() / 1000) + 3600; // Expires in one hour.
      try {
        const token = await generateToken(appId, appKey, channelId, userId, timestamp);
        // Join the channel. Parameters like token and timestamp are typically returned from the server.
        // Note: When calling this method, ensure the channelId, userId, appId, and timestamp parameters match those used to generate the token.
        await aliRtcEngine.joinChannel({
          channelId,
          userId,
          appId,
          token,
          timestamp,
        }, userName);
        // Joined the channel successfully. Proceed with other operations.
      } catch (error) {
        // Failed to join the channel.
      }
  6. Suivez ces étapes pour prévisualiser votre vidéo locale. Par défaut, après avoir rejoint un canal, les données audio et vidéo locales sont automatiquement capturées et publiées sur le Global Realtime Transport Network (GRTN).

    1. Dans le code HTML, ajoutez un élément VIDEO avec un id défini sur localPreviewer.

      <video
        id="localPreviewer"
        muted
        style="display: block;width: 320px;height: 180px;background-color: black;"
      ></video>
    2. Appelez la méthode setLocalViewConfig et transmettez l'ID de l'élément pour démarrer la prévisualisation.

      // The first parameter accepts an HTMLVideoElement or its ID. Pass null to stop the preview.
      // The second parameter specifies the stream type: 1 for a camera stream, 2 for a screen sharing stream.
      aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  7. Abonnez-vous aux flux audio et vidéo distants. Par défaut, après avoir rejoint un canal, le SDK s'abonne automatiquement aux flux audio et vidéo des autres diffuseurs. Les flux audio sont lus automatiquement. Pour afficher un flux de caméra ou un flux de partage d'écran, appelez la méthode setRemoteViewConfig.

    1. Dans le code HTML, ajoutez un élément DIV avec un id défini sur remoteVideoContainer pour servir de conteneur.

      <div id="remoteVideoContainer"></div>
    2. Surveillez les modifications d'abonnement aux flux vidéo distants. Lorsqu'un flux est abonné, lancez sa lecture en appelant la méthode setRemoteViewConfig. Lorsqu'il est désabonné, supprimez l'élément vidéo.

      // Store Video elements.
      const remoteVideoElMap = {};
      // The remote container 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];
        }
      }
      // This is the same example as in the "listen for and handle relevant events" step for `videoSubscribeStateChanged`.
      aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
        // `oldState` and `newState` are of the AliRtcSubscribeState type.
        // Values: 0 (initialized), 1 (unsubscribed), 2 (subscribing), 3 (subscribed).
        // `interval` is the time between state changes, in milliseconds.
        console.log(`Subscription state of remote user ${userId} in channel ${channelId} changed from ${oldState} to ${newState}.`);
        
        // Example handler
        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);
          // The first parameter is an HTMLVideoElement.
          // The second parameter is the remote user ID.
          // The third parameter specifies the stream type: 1 for a camera stream, 2 for a screen sharing stream.
          aliRtcEngine.setRemoteViewConfig(video, userId, 1);
        } else if (newState === 1) {
          removeRemoteVideo(userId);
        }
      });
  8. Terminez la session et libérez les ressources.

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

Démonstration de démarrage rapide

Important

Le code JavaScript de cette démonstration inclut une méthode generateToken pour calculer un jeton. Pour des raisons de sécurité, ne publiez jamais ce code ni votre AppKey dans un fichier JavaScript côté client, car cela pourrait entraîner des fuites d'informations et une utilisation abusive. Nous vous recommandons d'effectuer la signature du jeton sur votre serveur et de récupérer le jeton via une API authentifiée côté client.

Prérequis

Cette démonstration nécessite un serveur HTTP dans votre environnement de développement. Si vous ne disposez pas du package npm http-server, exécutez npm install --global http-server pour l'installer globalement.

Étape 1 : Créer le répertoire

Créez un dossier demo contenant deux fichiers : quick.html et quick.js.

- demo
  - quick.html
  - quick.js

Étape 2 : Modifier quick.html

Copiez le code suivant dans quick.html et enregistrez le fichier.

Exemple de 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">Login 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 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 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">Join Channel</button>
          <button id="leaveBtn" type="button" class="btn btn-secondary mb-2" disabled>Leave 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 Users</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/7.1.9/aliyun-rtc-sdk.js"></script>
    <script src="./quick.js"></script>
  </body>
</html>

Étape 3 : Modifier quick.js

Copiez le code suivant dans quick.js. Collez votre ID d'application et votre AppKey dans les variables spécifiées et enregistrez le fichier.

Exemple de 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();
}
// Enter 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;
  }
  // Fired when a remote user comes online.
  aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => {
    console.log(`User ${userId} joined the channel in ${elapsed} seconds.`);
    // Handle your business logic here, such as displaying the UI module for this user.
    showToast('onlineToast', `User ${userId} is online.`);
  });
  // Fired when a remote user goes offline.
  aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => {
    // `reason` is a reason code. For details, see the API reference.
    console.log(`User ${userId} left the channel. Reason code: ${reason}`);
    // Handle your business logic here, such as destroying the UI module for this user.
    showToast('offlineToast', `User ${userId} is offline.`);
    removeRemoteVideo(userId, 'camera');
    removeRemoteVideo(userId, 'screen');
  });
  aliRtcEngine.on('bye', code => {
    // `code` is a reason code. For details, see the API reference.
    console.log(`bye, code=${code}`);
    // Handle your business logic here, such as exiting the call page.
    showToast('loginToast', `You have left the channel. Reason code: ${code}`);
  });
  aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // 'oldState' and 'newState' are AliRtcSubscribeState values.
    // Values: 0 (initialized), 1 (unsubscribed), 2 (subscribing), 3 (subscribed).
    // `interval` is the time between state changes, in milliseconds.
    console.log(`Subscription state of remote user ${userId} in channel ${channelId} changed from ${oldState} to ${newState}.`);
    const vid = `camera_${userId}`;
    // Example handler
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // The first parameter is an HTMLVideoElement.
      // The second parameter is the remote user ID.
      // The third parameter specifies the stream type: 1 for a camera stream, 2 for a screen sharing stream.
      aliRtcEngine.setRemoteViewConfig(video, userId, 1);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'camera');
    }
  });
  aliRtcEngine.on('screenShareSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // 'oldState' and 'newState' are AliRtcSubscribeState values.
    // Values: 0 (initialized), 1 (unsubscribed), 2 (subscribing), 3 (subscribed).
    // `interval` is the time between state changes, in milliseconds.
    console.log(`Screen sharing stream subscription state for user ${userId} in channel ${channelId} changed from ${oldState} to ${newState}.`);
    const vid = `screen_${userId}`;
    // Example handler
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // The first parameter is an HTMLVideoElement.
      // The second parameter is the remote user ID.
      // The third parameter specifies the stream type: 1 for a camera stream, 2 for a screen sharing stream.
      aliRtcEngine.setRemoteViewConfig(video, userId, 2);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'screen');
    }
  });
}
$('#loginForm').submit(async e => {
  // Prevent the form's default submission action.
  e.preventDefault();
  const channelId = $('#channelId').val();
  const userId = $('#userId').val();
  const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;
  if (!channelId || !userId) {
    showToast('loginToast', 'Incomplete information.');
    return;
  }
  aliRtcEngine = AliRtcEngine.getInstance();
  listenEvents();
  try {
    const token = await generateToken(appId, appKey, channelId, userId, timestamp);
    // Set the channel mode. Valid values: 'communication' (communication mode), 'interactive_live' (interactive mode).
    aliRtcEngine.setChannelProfile('communication');
    // Set the user role. This method is effective only in interactive mode.
    // Valid values: 'interactive' (streamer, can publish and subscribe to streams), 'live' (viewer, can only subscribe to streams).
    // await aliRtcEngine.setClientRole('interactive');
    // Join the channel. Parameters like token and timestamp are typically returned from the server.
    await aliRtcEngine.joinChannel(
      {
        channelId,
        userId,
        appId,
        token,
        timestamp,
      },
      userId
    );
    showToast('loginToast', 'Successfully joined the channel.');
    $('#joinBtn').prop('disabled', true);
    $('#leaveBtn').prop('disabled', false);
    // Start the local preview.
    aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  } catch (error) {
    console.log('Failed to join the channel.', error);
    showToast('loginToast', 'Failed 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', 'Left the channel.');
});

Étape 4 : Exécuter la démonstration

  1. Dans votre terminal, accédez au dossier demo et exécutez http-server -p 8080 pour démarrer un serveur HTTP.

  2. Ouvrez un nouvel onglet dans votre navigateur et accédez à localhost:8080/quick.html. Saisissez un Channel ID et un User ID, puis cliquez sur Join Channel.

  3. Ouvrez un deuxième onglet dans votre navigateur et accédez à localhost:8080/quick.html. Saisissez le même Channel ID mais un User ID différent, puis cliquez sur Join Channel.

  4. Vérifiez que le flux multimédia de l'autre utilisateur est automatiquement abonné et affiché sur la page.

Questions fréquentes

Que faire si la reconnexion manuelle échoue ou si la reconnexion échoue après l'actualisation de la page ?

  • La reconnexion manuelle signale une erreur de création de flux en double : Le SDK dispose d'un mécanisme de reconnexion intégré ; une intervention au niveau du code n'est nécessaire qu'en cas d'échec de la reconnexion. Si vous déclenchez manuellement une reconnexion, vous devez correctement détruire le flux existant ou réutiliser l'instance existante avant de rejoindre à nouveau le canal, afin d'éviter de créer un flux en double alors qu'un flux existe déjà.

  • Échec de la reconnexion après l'actualisation de la page : Une actualisation de la page détruit l'instance du SDK ; vous devez donc suivre l'intégralité du processus de connexion en appelant à nouveau joinChannel. Nous vous recommandons d'écouter l'événement connectionStatusChange et, lorsqu'une déconnexion ou un échec est détecté, d'appeler leaveChannel puis de rejoindre à nouveau le canal pour effectuer la reconnexion.