日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

快速使用阿里云ARTC Web SDK

阿里云ARTC Web SDK是由阿里云提供的一套基于Web的實時通信開發工具。它允許開發者在Web應用中快速集成高質量的音視頻通話功能、實時消息傳遞等實時互動功能。本文為您演示快速搭建屬于自己的ARTC應用。

步驟一:開通應用

  1. 登錄視頻直播控制臺

  2. 在左側導航欄單擊直播+ > 實時音視頻 > 應用管理

  3. 單擊創建應用

  4. 填寫自定義的實例名稱,勾選服務協議后,點擊立即購買。

  5. 提示開通成功后,刷新應用管理頁面,即可查看您新建的實時音視頻應用。

    說明

    創建應用默認不產生費用 , 實際按照您具體云上用量后付費。更多信息,請參見實時音視頻費用

步驟二:獲取應用ID和AppKey

成功開通應用后,在應用管理列表中找到該應用,單擊操作欄中的管理按鈕,進入基本信息頁面,在該頁面獲取對應的應用IDAppKey

image

步驟三:集成接入

  1. 集成SDK。

    Script集成

    在您的HTML頁面引入SDK腳本。

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

    NPM集成

    在您的項目中使用npm安裝SDK。

    npm install aliyun-rtc-sdk --save
  2. 初始化引擎。

    // 以下兩種引入方式二選一
    // 當以 npm 包方式引入時執行
    import AliRtcEngine from 'aliyun-rtc-sdk';
    // 當以 Script 方式引入時執行
    const AliRtcEngine = window.AliRtcEngine;
    
    // 檢測環境
    const checkResult = await AliRtcEngine.isSupported();
    if (!checkResult.support) {
      // 當前環境不支持使用,提示用戶更換或升級瀏覽器
    }
    
    // 創建引擎實例,可以保存至全局變量中
    const aliRtcEngine = AliRtcEngine.getInstance();
    
  3. 創建好AliRtcEngine實例后,需要監聽、處理相關事件。

    // 當前用戶離開頻道
    aliRtcEngine.on('bye', (code) => {
      // code 為原因碼,具體含義請查看 API 文檔
      console.log(`bye, code=${code}`);
      // 這里做您的處理業務,如退出通話頁面等
    });
    
    // 監聽遠端用戶上線
    aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => {
      console.log(`用戶 ${userId} 加入頻道,耗時 ${elapsed} 秒`);
      // 這里處理您的業務邏輯,如展示這個用戶的模塊
    });
    
    // 監聽遠端用戶下線
    aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => {
      // reason 為原因碼,具體含義請查看 API 文檔
      console.log(`用戶 ${userId} 離開頻道,原因碼: ${reason}`);
      // 這里處理您的業務邏輯,如銷毀這個用戶的模塊
    });
    
    // 監聽遠端流訂閱變化
    aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
      // oldState、newState 類型均為AliRtcSubscribeState,值包含 0(初始化)、1(未訂閱)、2(訂閱中)、3(已訂閱)
      // interval 為兩個狀態之間的變化時間間隔,單位毫秒
      console.log(`頻道 ${channelId} 遠端用戶 ${userId} 訂閱狀態由 ${oldState} 變為 ${newState}`);
      // 這里處理觀看遠端流的邏輯
      // 當 newState 變為 3 時可以通過 setRemoteViewConfig 播放遠端流
      // 當 newState 變為 1 時可以停止播放
    });
    
    // 監聽鑒權信息過期
    aliRtcEngine.on('authInfoExpired', () => {
      // 該回調觸發代表鑒權信息已過期
      // 需要重新獲取 token 等數據,調用 refreshAuthInfo 接口更新鑒權數據
      aliRtcEngine.refreshAuthInfo({
        userId,
        token,
        timestamp
      });
    });
    
    // 監聽用戶鑒權信息即將過期
    aliRtcEngine.on('authInfoWillExpire', () => {
      // 該回調在鑒權信息30秒前觸發,收到該回調后應該及時更新鑒權信息
      // 若想要繼續在會中,需要重新獲取 token 等數據,調用 joinChannel 重新入會
    });
    
  4. (可選)設置頻道模式,默認通話模式。詳細信息,請參見設置頻道模式和用戶角色

    // 設置頻道模式,支持傳入字符串 communication(通話模式)、interactive_live(互動模式)
    aliRtcEngine.setChannelProfile('interactive_live');
    // 設置角色,互動模式時調用才生效
    // 支持傳入字符串 interactive(互動角色,允許推拉流)、live(觀眾角色,僅允許拉流)
    aliRtcEngine.setClientRole('interactive');
  5. 加入頻道。Token計算方式參見Token鑒權,您可以按需選擇單參數入會或者多參數入會的方案。

    • 單參數入會

      const userName = '測試用戶1'; // 可以修改為您的用戶名(支持中文)
      
      try {
        // fetchToken需要您來實現,從服務端獲取Base64Token
        const base64Token = await fetchToken();
        await aliRtcEngine.joinChannel(base64Token, userName);
        // 加入成功,繼續執行其他操作
      } catch (error) {
        // 加入失敗
      }
    • 多參數入會

      // 參考文檔 Token 鑒權部分,從服務端或本地生成鑒權信息
      // 注意:為了您的數據安全,任何情況下都不應該將帶有 appKey 的 token 計算邏輯發布給用戶
      const appId = 'yourAppId'; // 從控制臺獲取
      const appKey = 'yourAppKey'; // 從控制臺獲取,注意請勿在生產環境露出您的 AppKey
      const channelId = 'AliRtcDemo'; // 可以修改為您的頻道ID(僅支持英文字母、數字)
      const userId = 'test1'; // 可以修改為您的用戶ID(僅支持英文字母、數字)
      const userName = '測試用戶1'; // 可以修改為您的用戶名(支持中文)
      const timestamp = Math.floor(Date.now() / 1000) + 3600; // 一個小時后過期
      
      try {
        const token = await generateToken(appId, appKey, channelId, userId, timestamp);
        // 加入頻道,參數 token、nonce 等一般由服務端返回
        await aliRtcEngine.joinChannel({
          channelId,
          userId,
          appId,
          token,
          timestamp,
        }, userName);
        // 加入成功,繼續執行其他操作
      } catch (error) {
        // 加入失敗
      }
  6. 預覽畫面和推流。默認情況下,加入頻道后將自動采集本地的音視頻數據并推送至阿里云GRTN網絡中。您可以參考以下方式預覽您的本地畫面。

    1. 在HTML代碼中增加一個idlocalPreviewer的VIDEO元素。

      <video
        id="localPreviewer"
        muted
        style="display: block;width: 320px;height: 180px;background-color: black;"
      ></video>
    2. 通過setLocalViewConfig方法傳入元素ID開啟預覽。

      // 第一個參數支持傳入 HTMLVideoElement 或對應的元素 ID,傳入 null 時停止預覽
      // 第二個參數支持傳入 1 (預覽相機流)、2(預覽屏幕共享流)
      aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  7. 訂閱遠端音視頻流。默認情況下,加入頻道后將自動訂閱其他主播用戶的音視頻流,若有音頻流將自動播放,需要觀看相機流、屏幕流,則需要通過setRemoteViewConfig接口開啟。

    1. 在HTML代碼中增加一個idremoteVideoContainer的DIV元素作為容器。

      <div id="remoteVideoContainer"></div>
    2. 監聽到遠端視頻流訂閱變化后,若已訂閱setRemoteViewConfig接口播放,若未訂閱則移除。

      // 存儲 Video 元素
      const remoteVideoElMap = {};
      // 遠端容器元素
      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];
        }
      }
      
      // 同第二步監聽事件示例代碼中 videoSubscribeStateChanged 示例
      aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
        // oldState、newState 類型均為AliRtcSubscribeState,值包含 0(初始化)、1(未訂閱)、2(訂閱中)、3(已訂閱)
        // interval 為兩個狀態之間的變化時間間隔,單位毫秒
        console.log(`頻道 ${channelId} 遠端用戶 ${userId} 訂閱狀態由 ${oldState} 變為 ${newState}`);
        // 處理示例
        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);
          // 第一個參數傳入 HTMLVideoElement
          // 第二個參數傳入遠端用戶 ID
          // 第三個參數支持傳入 1 (預覽相機流)、2(預覽屏幕共享流)
          aliRtcEngine.setRemoteViewConfig(video, userId, 1);
        } else if (newState === 1) {
          removeRemoteVideo(userId);
        }
      });
  8. 結束流程。

    // 停止本地預覽
    await aliRtcEngine.stopPreview();
    // 離開頻道
    await aliRtcEngine.leaveChannel();
    // 銷毀實例
    aliRtcEngine.destroy();

快速體驗

前提條件

快速體驗demo需要您的開發環境啟動一個HTTP服務,如果您沒有安裝http-server的npm包,可以先執行npm install --global http-server指令全局安裝。

步驟一:創建目錄

創建一個demo文件夾,并按照下方文件目錄結構創建好quick.htmlquick.js兩個文件。

- demo
  - quick.html
  - quick.js

步驟二:編輯quick.html

將下方代碼復制到quick.html,并保存。

示例代碼

<!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"  />
    <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 快速開始</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">登錄消息</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">用戶上線</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">用戶下線</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">頻道號</label>
            <input class="form-control" id="channelId" />
          </div>
          <div class="form-group mb-2">
            <label for="userId" class="form-label">用戶ID</label>
            <input class="form-control" id="userId" />
          </div>
          <button id="joinBtn" type="submit" class="btn btn-primary mb-2">加入頻道</button>
          <button id="leaveBtn" type="button" class="btn btn-secondary mb-2" disabled>離開頻道</button>
        </form>
    
        <div class="mt-3">
          <h4>本地預覽</h4>
          <video
            id="localPreviewer"
            muted
            class="video"
          ></video>
        </div>
      </div>
      <div class="col-6">
        <h4>遠端用戶</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.12.3/aliyun-rtc-sdk.js"></script>
    <script src="./quick.js"></script>
  </body>
</html>

步驟三:編輯quick.js

將下方代碼復制到quick.js,并將應用IDAppKey粘貼至代碼指定變量中保存。

示例代碼

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();
}

// 填入您的應用ID 和 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;
  }
  // 監聽遠端用戶上線
  aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => {
    console.log(`用戶 ${userId} 加入頻道,耗時 ${elapsed} 秒`);
    // 這里處理您的業務邏輯,如展示這個用戶的模塊
    showToast('onlineToast', `用戶 ${userId} 上線`);
  });

  // 監聽遠端用戶下線
  aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => {
    // reason 為原因碼,具體含義請查看 API 文檔
    console.log(`用戶 ${userId} 離開頻道,原因碼: ${reason}`);
    // 這里處理您的業務邏輯,如銷毀這個用戶的模塊
    showToast('offlineToast', `用戶 ${userId} 下線`);
    removeRemoteVideo(userId, 'camera');
    removeRemoteVideo(userId, 'screen');
  });

  aliRtcEngine.on('bye', code => {
    // code 為原因碼,具體含義請查看 API 文檔
    console.log(`bye, code=${code}`);
    // 這里做您的處理業務,如退出通話頁面等
    showToast('loginToast', `您已離開頻道,原因碼: ${code}`);
  });

  aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState、newState 類型均為AliRtcSubscribeState,值包含 0(初始化)、1(未訂閱)、2(訂閱中)、3(已訂閱)
    // interval 為兩個狀態之間的變化時間間隔,單位毫秒
    console.log(`頻道 ${channelId} 遠端用戶 ${userId} 訂閱狀態由 ${oldState} 變為 ${newState}`);
    const vid = `camera_${userId}`;
    // 處理示例
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // 第一個參數傳入 HTMLVideoElement
      // 第二個參數傳入遠端用戶 ID
      // 第三個參數支持傳入 1 (預覽相機流)、2(預覽屏幕共享流)
      aliRtcEngine.setRemoteViewConfig(video, userId, 1);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'camera');
    }
  });

  aliRtcEngine.on('screenShareSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState、newState 類型均為AliRtcSubscribeState,值包含 0(初始化)、1(未訂閱)、2(訂閱中)、3(已訂閱)
    // interval 為兩個狀態之間的變化時間間隔,單位毫秒
    console.log(`頻道 ${channelId} 遠端用戶 ${userId} 屏幕流的訂閱狀態由 ${oldState} 變為 ${newState}`);
    const vid = `screen_${userId}`;
    // 處理示例    
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // 第一個參數傳入 HTMLVideoElement
      // 第二個參數傳入遠端用戶 ID
      // 第三個參數支持傳入 1 (預覽相機流)、2(預覽屏幕共享流)
      aliRtcEngine.setRemoteViewConfig(video, userId, 2);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'screen');
    }
  });
}

$('#loginForm').submit(async e => {
  // 防止表單默認提交動作
  e.preventDefault();
  const channelId = $('#channelId').val();
  const userId = $('#userId').val();
  const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;

  if (!channelId || !userId) {
    showToast('loginToast', '數據不完整');
    return;
  }

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

  try {
    const token = await generateToken(appId, appKey, channelId, userId, timestamp);
    // 設置頻道模式,支持傳入字符串 communication(通話模式)、interactive_live(互動模式)
    aliRtcEngine.setChannelProfile('communication');
    // 設置角色,互動模式時調用才生效
    // 支持傳入字符串 interactive(互動角色,允許推拉流)、live(觀眾角色,僅允許拉流)
    // aliRtcEngine.setClientRole('interactive');
    // 加入頻道,參數 token、nonce 等一般有服務端返回
    await aliRtcEngine.joinChannel(
      {
        channelId,
        userId,
        appId,
        token,
        timestamp,
      },
      userId
    );
    showToast('loginToast', '加入頻道成功');
    $('#joinBtn').prop('disabled', true);
    $('#leaveBtn').prop('disabled', false);

    // 預覽
    aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  } catch (error) {
    console.log('加入頻道失敗', error);
    showToast('loginToast', '加入頻道失敗');
  }
});

$('#leaveBtn').click(async () => {
  Object.keys(remoteVideoElMap).forEach(vid => {
    const arr = vid.split('_');
    removeRemoteVideo(arr[1], arr[0]);
  });
  // 停止本地預覽
  await aliRtcEngine.stopPreview();
  // 離開頻道
  await aliRtcEngine.leaveChannel();
  // 銷毀實例
  aliRtcEngine.destroy();
  aliRtcEngine = undefined;
  $('#joinBtn').prop('disabled', false);
  $('#leaveBtn').prop('disabled', true);
  showToast('loginToast', '已離開頻道');
});

步驟四:運行體驗

  1. 在終端中進入demo文件夾,然后執行http-server -p 8080,啟動一個HTTP服務。

  2. 瀏覽器中新建標簽頁,訪問localhost:8080/quick.html,在界面上填入頻道ID用戶ID ,單擊加入頻道按鈕。

  3. 瀏覽器中再新建一個標簽頁,訪問localhost:8080/quick.html,在界面上填入與上一步相同的頻道ID和另一個用戶ID ,單擊加入頻道按鈕。

  4. 界面上將自動訂閱另一個用戶的媒體流。