Todos os produtos
Search
Central de documentação

ApsaraVideo Live:Primeiros passos com o ARTC Web SDK

Última atualização: Jun 30, 2026

O ApsaraVideo Real-time Communication (ARTC) Web SDK é um conjunto de ferramentas da Alibaba Cloud para desenvolver aplicações web de comunicação em tempo real. Ele permite integrar rapidamente recursos de alta qualidade, como chamadas de áudio e vídeo e mensagens em tempo real, às suas aplicações web. Este guia mostra como criar sua primeira aplicação ARTC de forma ágil.

Etapa 1: Criar uma aplicação

  1. Faça login no ApsaraVideo Live console.

  2. No painel de navegação à esquerda, escolha Live + > ApsaraVideo Real-time Communication > Applications.

  3. Clique em Create Application.

  4. Insira um instance name personalizado, marque a caixa de seleção Terms of Service e clique em Purchase Now.

  5. Após a exibição da mensagem de sucesso, atualize a página Applications para visualizar sua nova aplicação do ApsaraVideo Real-time Communication.

    Nota

    A criação da aplicação é gratuita. A cobrança ocorre no modelo de pagamento conforme o uso, baseada no consumo real. Para mais informações, consulte Faturamento de chamadas de áudio e vídeo.

Etapa 2: Obter o ID da aplicação e a AppKey

Após criar a aplicação, localize-a na lista de aplicações. Na coluna Actions, clique em Manage para abrir a página Basic Information. Nessa página, localize o Application ID e a AppKey.

Etapa 3: Integrar o SDK

  1. Integre o SDK.

    Script

    Inclua o script do SDK na página HTML.

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

    NPM

    Execute o comando abaixo no projeto para instalar o SDK.

    npm install aliyun-rtc-sdk --save
  2. Inicialize o engine.

    // 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. Após criar a instância do AliRtcEngine, configure listeners para os eventos relevantes.

    // 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. (Opcional) Defina o modo do canal. O padrão é o modo de comunicação. Para mais detalhes, consulte Definir o modo do canal e a função do usuário.

    // 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. Entre em um canal. Para saber como gerar um token, consulte autenticação baseada em token. Escolha entrar com um único parâmetro ou com múltiplos parâmetros, conforme sua necessidade.

    • Entrar com um único parâmetro

      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.
      }
    • Entrar com múltiplos parâmetros

      // 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. Siga estas etapas para pré-visualizar o vídeo local. Por padrão, ao entrar em um canal, os dados locais de áudio e vídeo são capturados automaticamente e publicados na Global Realtime Transport Network (GRTN).

    1. Adicione um elemento VIDEO com id igual a localPreviewer no código HTML.

      <video
        id="localPreviewer"
        muted
        style="display: block;width: 320px;height: 180px;background-color: black;"
      ></video>
    2. Chame o método setLocalViewConfig e passe o ID do elemento para iniciar a pré-visualização.

      // 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. Assine os streams remotos de áudio e vídeo. Por padrão, após entrar em um canal, o SDK assina automaticamente os streams de áudio e vídeo de outros streamers. Os streams de áudio são reproduzidos automaticamente. Para exibir um stream de câmera ou de compartilhamento de tela, chame o método setRemoteViewConfig.

    1. Adicione um elemento DIV com id igual a remoteVideoContainer no código HTML para servir como contêiner.

      <div id="remoteVideoContainer"></div>
    2. Monitore as alterações de assinatura dos streams de vídeo remotos. Quando um stream for assinado, reproduza-o chamando o método setRemoteViewConfig. Caso a assinatura seja cancelada, remova o elemento de vídeo.

      // 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. Encerre a sessão e limpe os recursos.

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

Demo de início rápido

Importante

O JavaScript desta demo inclui um método generateToken para calcular o token. Por motivos de segurança, nunca publique este código ou sua AppKey em um arquivo JavaScript do lado do cliente, pois isso pode causar vazamento de informações e uso indevido. Recomendamos realizar a assinatura do token no servidor e obtê-lo por meio de uma API autenticada no cliente.

Pré-requisitos

Esta demo requer um servidor HTTP no ambiente de desenvolvimento. Caso não tenha o pacote npm http-server, execute npm install --global http-server para instalá-lo globalmente.

Etapa 1: Criar o diretório

Crie uma pasta demo contendo dois arquivos: quick.html e quick.js.

- demo
  - quick.html
  - quick.js

Etapa 2: Editar quick.html

Copie o código abaixo para quick.html e salve o arquivo.

Exemplo de código

<!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>

Etapa 3: Editar quick.js

Copie o código abaixo para quick.js. Cole seu application ID e sua AppKey nas variáveis indicadas e salve o arquivo.

Exemplo de código

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.');
});

Etapa 4: Executar a demo

  1. No terminal, navegue até a pasta demo e execute http-server -p 8080 para iniciar um servidor HTTP.

  2. Abra uma nova aba no navegador e acesse localhost:8080/quick.html. Insira um Channel ID e um User ID, depois clique em Join Channel.

  3. Abra uma segunda aba no navegador e acesse localhost:8080/quick.html. Insira o mesmo Channel ID, mas use um User ID diferente, e clique em Join Channel.

  4. Verifique se o stream de mídia do outro usuário foi assinado automaticamente e está sendo exibido na página.