视频互动直播是以后比拟热门的玩法,咱们常常见到有PK 连麦、直播答题、一起 KTV、电商直播、互动大班课、视频相亲等。本文将演示如何通过声网 视频 SDK 在 Web 端实现一个视频直播利用。话不多说,咱们开始入手实操。

前提筹备

在声网开发者控制台 Console https://console.agora.io 注册声网开发者账号后,须要获取我的项目 AppID。另外,开发者每个月可取得 10000 分钟的收费应用额度,可实现各类实时音视频场景。

先来体验下 Demo

咱们在 GitHub 上提供一个开源的根底视频通话示例我的项目,在开始开发之前你能够通过该示例我的项目体验音视频通话成果。

  • 在线 demo:https://webdemo.agora.io/basicVideoCall/index.html
  • 源码 Github 地址:https://github.com/AgoraIO/API-Examples-Web/tree/main/Demo/basicVideoCall

入手实际

从 Web 前端页面引入声网 SDK,发动视频通话。

开发环境

声网 SDK 的兼容性良好,对硬件设施和软件系统的要求不高,开发环境和测试环境满足以下条件即可,以下是本文的开发环境和测试环境:

  • 浏览器:Chrome、Firefox、Safari 及 Edge
  • 开发环境

    • MacBook Pro (13-inch, M1, 2020)
    • Visual Studio Code (1.67.1)
    • AgoraWebSDK (4.12.2)
  • 测试环境

    • Chrome (101.0.4951.64)

手动集成设置

文件组织构造

实现视频通话之前,参考如下步骤设置你的我的项目:
如需创立新我的项目,能够在 Visual Studio Code 里 File > New Window,创立 Web 我的项目。残缺的目录构造如下,依据集体教训会有所变动。

.├── index.css # 用于设计 Web 利用的用户界面款式├── index.html # 用于设计 Web 利用的用户界面├── index.js # 通过 AgoraRTCClient 实现具体应用逻辑的代码。└── vendor # 第三方前端插件,辅助页面布局和交互,本教程中是下载到本地应用,你也能够应用 CDN 的形式    ├── bootstrap.bundle.min.js    ├── bootstrap.min.css    └── jquery-3.4.1.min.js

前端页面集成声网 SDK

声网能够下载到本地应用,也能够间接应用声网的 CDN 引入, 本文举荐应用 CDN 形式集成Agora SDK。

在 index.html 中增加以下代码

<!DOCTYPE html>...  <link rel="stylesheet" href="./vendor/bootstrap.min.css">  <link rel="stylesheet" href="./index.css">...  <script src="./vendor/jquery-3.4.1.min.js"></script>  <script src="./vendor/bootstrap.bundle.min.js"></script>  <script src="https://download.agora.io/sdk/release/AgoraRTC_N.js"></script>  <script src="./index.js"></script>...
最终残缺代码为

能够间接复制运行。

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <title>Basic Video Call -- Agora</title>  <link rel="stylesheet" href="./vendor/bootstrap.min.css">  <link rel="stylesheet" href="./index.css"></head><body>  <div class="container-fluid banner">    <p class="banner-text">Basic Video Call</p>    <a style="color: rgb(255, 255, 255);fill: rgb(255, 255, 255);fill-rule: evenodd; position: absolute; right: 10px; top: 4px;"      class="Header-link " href="https://github.com/AgoraIO-Community/AgoraWebSDK-NG/tree/master/Demo">      <svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>    </a>  </div>    <div id="success-alert" class="alert alert-success alert-dismissible fade show" role="alert">    <strong>Congratulations!</strong><span> You can invite others join this channel by click </span><a href="" target="_blank">here</a>    <button type="button" class="close" data-dismiss="alert" aria-label="Close">      <span aria-hidden="true">&times;</span>    </button>  </div>  <div id="success-alert-with-token" class="alert alert-success alert-dismissible fade show" role="alert">    <strong>Congratulations!</strong><span> Joined room successfully. </span>    <button type="button" class="close" data-dismiss="alert" aria-label="Close">      <span aria-hidden="true">&times;</span>    </button>  </div>  <div id="success-alert-with-token" class="alert alert-success alert-dismissible fade show" role="alert">    <strong>Congratulations!</strong><span> Joined room successfully. </span>    <button type="button" class="close" data-dismiss="alert" aria-label="Close">      <span aria-hidden="true">&times;</span>    </button>  </div>     <div class="container">    <form id="join-form">      <div class="row join-info-group">          <div class="col-sm">            <p class="join-info-text">AppID</p>            <input id="appid" type="text" placeholder="enter appid" required>            <p class="tips">If you don`t know what is your appid, checkout <a href="https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#a-nameappidaapp-id">this</a></p>          </div>          <div class="col-sm">            <p class="join-info-text">Token(optional)</p>            <input id="token" type="text" placeholder="enter token">            <p class="tips">If you don`t know what is your token, checkout <a href="https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#a-namekeyadynamic-key">this</a></p>          </div>          <div class="col-sm">            <p class="join-info-text">Channel</p>            <input id="channel" type="text" placeholder="enter channel name" required>            <p class="tips">If you don`t know what is your channel, checkout <a href="https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#channel">this</a></p>          </div>      </div>       <div class="button-group">        <button id="join" type="submit" class="btn btn-primary btn-sm">Join</button>        <button id="leave" type="button" class="btn btn-primary btn-sm" disabled>Leave</button>      </div>    </form>     <div class="row video-group">      <div class="col">        <p id="local-player-name" class="player-name"></p>        <div id="local-player" class="player"></div>      </div>      <div class="w-100"></div>      <div class="col">        <div id="remote-playerlist"></div>      </div>    </div>  </div>   <script src="./vendor/jquery-3.4.1.min.js"></script>  <script src="./vendor/bootstrap.bundle.min.js"></script>  <script src="https://download.agora.io/sdk/release/AgoraRTC_N.js"></script>  <script src="./index.js"></script></body></html>

视频通话逻辑

注:以下代码都将在 index.js 中增加

1)初始化Client
var client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
2)退出RTC 频道并创立本地音频轨道
// Join a channel and create local tracks. Best practice is to use Promise.all and run them concurrently.[ options.uid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([  // Join the channel.  client.join(options.appid, options.channel, options.token || null, options.uid || null),  // Create tracks to the local microphone and camera.  AgoraRTC.createMicrophoneAudioTrack(),  AgoraRTC.createCameraVideoTrack()]);
3)播放本地视频
// Play the local video track to the local browser and update the UI with the user ID.localTracks.videoTrack.play("local-player");
4)公布本地音视频到频道中
// Publish the local video and audio tracks to the channel.await client.publish(Object.values(localTracks));
5)监听远端用户音视频
// Add an event listener to play remote tracks when remote user publishes.client.on("user-published", handleUserPublished);client.on("user-unpublished", handleUserUnpublished); function handleUserPublished(user, mediaType) {  const id = user.uid;  remoteUsers[id] = user;  subscribe(user, mediaType);} function handleUserUnpublished(user, mediaType) {  if (mediaType === 'video') {    const id = user.uid;    delete remoteUsers[id];    $(`#player-wrapper-${id}`).remove();  }}  async function subscribe(user, mediaType) {  const uid = user.uid;  // subscribe to a remote user  await client.subscribe(user, mediaType);  console.log("subscribe success");  if (mediaType === 'video') {    const player = $(`      <div id="player-wrapper-${uid}">        <p class="player-name">remoteUser(${uid})</p>        <div id="player-${uid}" class="player"></div>      </div>    `);    $("#remote-playerlist").append(player);    user.videoTrack.play(`player-${uid}`);  }   if (mediaType === 'audio') {    user.audioTrack.play();  }}
6)来到频道
async function leave() {  for (trackName in localTracks) {    var track = localTracks[trackName];    if(track) {      track.stop();      track.close();      localTracks[trackName] = undefined;    }  }   // Remove remote users and player views.  remoteUsers = {};  $("#remote-playerlist").html("");   // leave the channel  await client.leave(); }
最终残缺的代码
// create Agora clientvar client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });  var localTracks = {  videoTrack: null,  audioTrack: null};var remoteUsers = {};// Agora client optionsvar options = {  appid: null,  channel: null,  uid: null,  token: null}; // the demo can auto join channel with params in url$(() => {  var urlParams = new URL(location.href).searchParams;  options.appid = urlParams.get("appid");  options.channel = urlParams.get("channel");  options.token = urlParams.get("token");  if (options.appid && options.channel) {    $("#appid").val(options.appid);    $("#token").val(options.token);    $("#channel").val(options.channel);    $("#join-form").submit();  }}) $("#join-form").submit(async function (e) {  e.preventDefault();  $("#join").attr("disabled", true);  try {    options.appid = $("#appid").val();    options.token = $("#token").val();    options.channel = $("#channel").val();    await join();    if(options.token) {      $("#success-alert-with-token").css("display", "block");    } else {      $("#success-alert a").attr("href", `index.html?appid=${options.appid}&channel=${options.channel}&token=${options.token}`);      $("#success-alert").css("display", "block");    }  } catch (error) {    console.error(error);  } finally {    $("#leave").attr("disabled", false);  }}) $("#leave").click(function (e) {  leave();}) async function join() {   // add event listener to play remote tracks when remote user publishs.  client.on("user-published", handleUserPublished);  client.on("user-unpublished", handleUserUnpublished);   // join a channel and create local tracks, we can use Promise.all to run them concurrently  [ options.uid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([    // join the channel    client.join(options.appid, options.channel, options.token || null),    // create local tracks, using microphone and camera    AgoraRTC.createMicrophoneAudioTrack(),    AgoraRTC.createCameraVideoTrack()  ]);     // play local video track  localTracks.videoTrack.play("local-player");  $("#local-player-name").text(`localVideo(${options.uid})`);   // publish local tracks to channel  await client.publish(Object.values(localTracks));  console.log("publish success");} async function leave() {  for (trackName in localTracks) {    var track = localTracks[trackName];    if(track) {      track.stop();      track.close();      localTracks[trackName] = undefined;    }  }   // remove remote users and player views  remoteUsers = {};  $("#remote-playerlist").html("");   // leave the channel  await client.leave();   $("#local-player-name").text("");  $("#join").attr("disabled", false);  $("#leave").attr("disabled", true);  console.log("client leaves channel success");} async function subscribe(user, mediaType) {  const uid = user.uid;  // subscribe to a remote user  await client.subscribe(user, mediaType);  console.log("subscribe success");  if (mediaType === 'video') {    const player = $(`      <div id="player-wrapper-${uid}">        <p class="player-name">remoteUser(${uid})</p>        <div id="player-${uid}" class="player"></div>      </div>    `);    $("#remote-playerlist").append(player);    user.videoTrack.play(`player-${uid}`);  }  if (mediaType === 'audio') {    user.audioTrack.play();  }} function handleUserPublished(user, mediaType) {  const id = user.uid;  remoteUsers[id] = user;  subscribe(user, mediaType);} function handleUserUnpublished(user) {  const id = user.uid;  delete remoteUsers[id];  $(`#player-wrapper-${id}`).remove();}

运行成果

在浏览器开两个 tab 运行网页,应用两个用户退出同一个频道,如果能看见两个本人,阐明你胜利了。

残缺代码工程下载

https://download.agora.io/sdk/release/Agora_Web_SDK_v4_14_0_FULL.zip


以上就是基于声网 Web SDK 实现一对一视频通话的全部内容。有问题欢送到「RTE 开发者社区」https://www.agora.io/cn/community/ 交换吐槽。