写点什么

基于 Agora SDK 实现 Web 端的多人视频互动

  • 2020-02-26
  • 本文字数:9231 字

    阅读完需:约 30 分钟

基于 Agora SDK 实现 Web 端的多人视频互动

根据本文指导快速集成 Agora Web SDK 并在你自己的 app 里实现音视频互动直播。


本文会详细介绍如何建立一个简单的项目并使用 Agora Web SDK 实现基础的互动直播。我们建议你阅读本文以快速了解 Agora 的核心方法。


互动直播和实时通话的区别在于,直播频道的用户有角色之分。你可以将角色设置为主播,或者观众,其中主播可以收、发流,观众只能收流。


由于浏览器的安全策略对除 127.0.0.1 以外的 HTTP 地址作了限制,Agora Web SDK 仅支持 HTTPS 协议或者 http://localhosthttp://127.0.0.1),请勿使用 HTTP 协议部署你的项目。

Demo 体验

我们在 GitHub 上提供一个开源的基础视频互动直播示例项目,在开始开发之前你可以通过该示例项目体验互动直播效果。

前提条件

  1. 安装一款 Agora Web SDK 支持的浏览器,如下表所示:

  2. 获得一个有效的 Agora 账号。(免费注册)

  3. 如果你的网络环境部署了防火墙,请根据声网文档中心的「应用企业防火墙限制」打开相关端口。

设置开发环境

你需要准备一个自己的项目并且将 Agora Web SDK 集成到其中。

创建 Web 项目

如果你已经有一个 Web 项目了,跳过该节,直接阅读集成 SDK。


我们提供的示例代码使用了一些第三方的库文件来实现页面的样式和布局,你可以在 Github repo 中查找一下文件,或者使用其他方式实现。


  • common.css

  • jquery.min.js

  • materialize.min.js

  • 这个项目只需要用到一个 HTML 文件。


  1. 新建一个 HTML 文件。这里我们将文件命名为 index.html(以下简称项目文件)。

  2. 用一个代码编辑器(例如 VS Code)打开该文件。

  3. 复制以下代码,粘贴到项目文件中。

  4. 该步骤会为你的项目创建前端页面的 UI,你也可以自定义你的 UI。以下是示例代码:


<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">  <title>Basic Live Broadcast</title>  <link rel="stylesheet" href="./assets/common.css" /></head><body class="agora-theme">  <div class="navbar-fixed">    <nav class="agora-navbar">      <div class="nav-wrapper agora-primary-bg valign-wrapper">        <h5 class="left-align">Basic Live Broadcast</h5>      </div>    </nav>  </div>  <form id="form" class="row col l12 s12">    <div class="row container col l12 s12">      <div class="col" style="min-width: 433px; max-width: 443px">        <div class="card" style="margin-top: 0px; margin-bottom: 0px;">          <div class="row card-content" style="margin-bottom: 0px;">              <div class="input-field">                <label for="appID" class="active">App ID</label>                <input type="text" placeholder="App ID" name="appID">              </div>              <div class="input-field">                <label for="channel" class="active">Channel</label>                <input type="text" placeholder="channel" name="channel">              </div>              <div class="input-field">                <label for="token" class="active">Token</label>                <input type="text" placeholder="token" name="token">              </div>              Host: <input id="role" type="checkbox" checked></input>              <div class="row" style="margin: 0">                <div class="col s12">                <button class="btn btn-raised btn-primary waves-effect waves-light" id="join">JOIN</button>                <button class="btn btn-raised btn-primary waves-effect waves-light" id="leave">LEAVE</button>                <button class="btn btn-raised btn-primary waves-effect waves-light" id="publish">PUBLISH</button>                <button class="btn btn-raised btn-primary waves-effect waves-light" id="unpublish">UNPUBLISH</button>                </div>              </div>          </div>        </div>      </div>      <div class="col s7">        <div class="video-grid" id="video">          <div class="video-view">            <div id="local_stream" class="video-placeholder"></div>            <div id="local_video_info" class="video-profile hide"></div>            <div id="video_autoplay_local" class="autoplay-fallback hide"></div>          </div>        </div>      </div>    </div>  </form><script src="vendor/jquery.min.js"></script><script src="vendor/materialize.min.js"></script></body></html>
复制代码

集成 SDK

选择如下任意一种方法获取 Agora Web SDK:


方法 1. 使用 npm 获取 SDK


使用该方法需要先安装 npm,详见 npm 快速入门。


  1. 运行安装命令


npm install agora-rtc-sdk
复制代码


  1. 在你的项目的 Javascript 代码中添加一行:


import AgoraRTC from 'agora-rtc-sdk'
复制代码


方法 2. 使用 CDN 方法获取 SDK


该方法无需下载安装包。在项目文件中,将以下代码添加到上一行:</p><pre><code>&lt;script&nbsp;src=&quot;https://cdn.agora.io/sdk/release/AgoraRTCSDK-3.0.0.js&quot;&gt;&lt;/script&gt;<br/></code></pre><p>方法 3. 从官网获取 SDK</p><ol><li>下载最新版 Agora Web SDK 软件包。</li><li>将下载下来的软件包中的 AgoraRTCSDK-3.0.0.js 文件保存到项目文件所在的目录下。</li><li>在项目文件中,将如下代码添加到<style>上一行:</li></ol><pre><code>&lt;script&nbsp;src=&quot;./AgoraRTCSDK-3.0.0.js&quot;&gt;&lt;/script&gt;<br/></code></pre><p>为方便起见,这里我们选择第二种方法,直接使用 CDN 链接。<br/>现在,我们已经将 Agora Web SDK 集成到项目中了。接下来我们要通过调用 Agora Web SDK 提供的核心 API 实现基础的互动直播功能。</p><h2>实现互动直播</h2><p>本节介绍如何使用 Agora Web SDK 实现互动直播。</p><p>在使用 Agora Web SDK 时,你会经常用到以下两种对象:</p><ul><li>Client 对象,代表一个本地客户端。Client 类的方法提供了音视频通话的主要功能,例如加入频道、发布音视频流等。</li><li>Stream 对象,代表本地和远端的音视频流。Stream 类的方法用于定义音视频流对象的行为,例如流的播放控制、音视频的编码配置等。调用 Stream 方法时,请注意区分本地流和远端流对象。<br/>下图展示了基础互动直播的 API 调用。注意图中的方法是对不同的对象调用的。</li></ul><p><img src="https://static001.infoq.cn/resource/image/94/47/94f50891c80418c172345becaedcf647.jpg" alt=""/></p><blockquote><p>本文只介绍 Agora Web SDK 最基础的方法和回调。完整的 API 方法和回调详见 Web API 参考。</p></blockquote><p>为方便起见,我们为下面要用到的示例代码定义了两个变量。此步骤不是必须的,你可以根据你的项目有其他的实现。</p><pre><code>//&nbsp;rtc&nbsp;object<br/>var&nbsp;rtc&nbsp;=&nbsp;{<br/>&nbsp;&nbsp;client:&nbsp;null,<br/>&nbsp;&nbsp;joined:&nbsp;false,<br/>&nbsp;&nbsp;published:&nbsp;false,<br/>&nbsp;&nbsp;localStream:&nbsp;null,<br/>&nbsp;&nbsp;remoteStreams:&nbsp;[],<br/>&nbsp;&nbsp;params:&nbsp;{}<br/>};<br/><br/>//&nbsp;Options&nbsp;for&nbsp;joining&nbsp;a&nbsp;channel<br/>var&nbsp;option&nbsp;=&nbsp;{<br/>&nbsp;&nbsp;appID:&nbsp;&quot;Your&nbsp;App&nbsp;ID&quot;,<br/>&nbsp;&nbsp;channel:&nbsp;&quot;Channel&nbsp;name&quot;,<br/>&nbsp;&nbsp;uid:&nbsp;null,<br/>&nbsp;&nbsp;token:&nbsp;&quot;Your&nbsp;token&quot;<br/>}<br/></code></pre><p>初始化客户端</p><p>加入频道前,我们需要先创建并初始化一个客户端对象。</p><pre><code>&nbsp;//&nbsp;Create&nbsp;a&nbsp;client<br/>&nbsp;rtc.client&nbsp;=&nbsp;AgoraRTC.createClient({mode:&nbsp;&quot;rtc&quot;,&nbsp;codec:&nbsp;&quot;h264&quot;});<br/><br/>&nbsp;//&nbsp;Initialize&nbsp;the&nbsp;client<br/>&nbsp;rtc.client.init(option.appID,&nbsp;function&nbsp;()&nbsp;{<br/>&nbsp;&nbsp;&nbsp;console.log(&quot;init&nbsp;success&quot;);<br/>&nbsp;&nbsp;&nbsp;},&nbsp;(err)&nbsp;=&gt;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;console.error(err);<br/>&nbsp;});<br/></code></pre><p>在 AgoraRTC.createClient 方法中,需注意 mode 和 codec 这两个参数的设置:</p><ul><li>mode 用于设置频道模式。一对一或多人通话中,建议设为 “rtc” ,使用通信模式;互动直播中,建议设为 “live”,使用直播模式。</li><li>codec 用于设置浏览器使用的编解码格式。如果你需要使用 Safari 12.1 及之前版本,将该参数设为 “h264”;如果你需要在手机上使用 Agora Web SDK,请参考移动端使用 Web SDK。<br/>你需要在该步骤中填入项目的 App ID。请参考如下步骤在控制台创建 Agora 项目并获取 App ID。</li></ul><ol><li>登录控制台,点击左侧导航栏的项目管理图标 。</li><li>点击创建,按照屏幕提示设置项目名,选择一种鉴权机制,然后点击提交。</li><li>在项目管理页面,你可以获取该项目的 App ID。<br/>设置用户角色</li></ol><p>直播频道有两种用户角色:主播和观众,其中默认的角色为观众。设置频道模式为直播后,你可以在 App 中参考如下步骤设置用户角色:</p><ol><li>让用户选择自己的角色是主播(“host”)还是观众(“audience”)。</li><li>调用 setClientRole 方法,传入用户选择的角色。</li></ol><pre><code>//&nbsp;The&nbsp;value&nbsp;of&nbsp;role&nbsp;can&nbsp;be&nbsp;&quot;host&quot;&nbsp;or&nbsp;&quot;audience&quot;.<br/>rtc.client.setClientRole(role);&nbsp;<br/></code></pre><p>直播频道内的用户,只能看到主播的画面、听到主播的声音。加入频道后,如果你想切换用户角色,也可以调用 setClientRole 方法。</p><p>加入频道</p><p>在 Client.init 的 onSuccess 回调中调用 Client.join 加入频道。</p><pre><code>&nbsp;//&nbsp;Join&nbsp;a&nbsp;channel<br/>&nbsp;rtc.client.join(option.token&nbsp;?&nbsp;option.token&nbsp;:&nbsp;null,&nbsp;option.channel,&nbsp;option.uid&nbsp;?&nbsp;+option.uid&nbsp;:&nbsp;null,&nbsp;function&nbsp;(uid)&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;join&nbsp;channel:&nbsp;&quot;&nbsp;+&nbsp;option.channel&nbsp;+&nbsp;&quot;&nbsp;success,&nbsp;uid:&nbsp;&quot;&nbsp;+&nbsp;uid);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rtc.params.uid&nbsp;=&nbsp;uid;<br/>&nbsp;&nbsp;&nbsp;},&nbsp;function(err)&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.error(&quot;client&nbsp;join&nbsp;failed&quot;,&nbsp;err)<br/>&nbsp;})<br/></code></pre><p>在 Client.join 中注意以下参数的设置:</p><ul><li>token: 该参数为可选。如果你的 Agora 项目开启了 App 证书,你需要在该参数中传入一个 Token,详见 使用 Token。</li><li>在测试环境,我们推荐使用控制台生成临时 Token,详见获取临时 Token。</li><li>在生产环境,我们推荐你在自己的服务端生成 Token,详见 生成 Token.</li><li>channel: 频道名,长度在 64 字节以内的字符串。</li><li>uid: 用户 ID,频道内每个用户的 UID 必须是唯一的。如果你将 uid 设为 null,Agora 会自动分配一个 UID 并在 onSuccess 回调中返回。<br/>更多的参数设置注意事项请参考 Client.join 接口中的参数描述。</li></ul><h3>发布本地流</h3><p>如果用户角色设置为主播,我们需要创建并发布本地流。</p><ol><li>在 Client.join 的 onSuccess 回调中调用 AgoraRTC.createStream 方法创建一个本地音视频流。<br/>在创建流时,通过设置 audio 和 video 参数来控制是否发布音频和视频。</li></ol><pre><code>//&nbsp;Create&nbsp;a&nbsp;local&nbsp;stream<br/>rtc.localStream&nbsp;=&nbsp;AgoraRTC.createStream({<br/>&nbsp;&nbsp;streamID:&nbsp;rtc.params.uid,<br/>&nbsp;&nbsp;audio:&nbsp;true,<br/>&nbsp;&nbsp;video:&nbsp;true,<br/>&nbsp;&nbsp;screen:&nbsp;false,<br/>})<br/>2.&nbsp;调用 &nbsp;Stream.init&nbsp;方法初始化创建的流。<br/>//&nbsp;Initialize&nbsp;the&nbsp;local&nbsp;stream<br/>rtc.localStream.init(function&nbsp;()&nbsp;{<br/>&nbsp;&nbsp;console.log(&quot;init&nbsp;local&nbsp;stream&nbsp;success&quot;);<br/>},&nbsp;function&nbsp;(err)&nbsp;{<br/>&nbsp;&nbsp;console.error(&quot;init&nbsp;local&nbsp;stream&nbsp;failed&nbsp;&quot;,&nbsp;err);<br/>})<br/></code></pre><p>在初始化流时,浏览器会跳出弹窗要求摄像头和麦克风权限,请确保授权。<br/>3. 在 Stream.init 的 onSuccess 回调中调用 Client.publish 方法,发布本地流。</p><pre><code>//&nbsp;Publish&nbsp;the&nbsp;local&nbsp;stream<br/>rtc.client.publish(rtc.localStream,&nbsp;function&nbsp;(err)&nbsp;{<br/>&nbsp;&nbsp;console.log(&quot;publish&nbsp;failed&quot;);<br/>&nbsp;&nbsp;console.error(err);<br/>})<br/></code></pre><h3>订阅远端流</h3><p>当远端流加入频道时,会触发 stream-added 事件,我们需要通过 Client.on 监听该事件并在回调中订阅新加入的远端流。</p><p>建议在创建客户端对象之后立即监听事件。</p><ol><li>监听 “stream-added” 事件,当有远端流加入时订阅该流。</li></ol><pre><code>rtc.client.on(&quot;stream-added&quot;,&nbsp;function&nbsp;(evt)&nbsp;{&nbsp;&nbsp;<br/>&nbsp;&nbsp;var&nbsp;remoteStream&nbsp;=&nbsp;evt.stream;<br/>&nbsp;&nbsp;var&nbsp;id&nbsp;=&nbsp;remoteStream.getId();<br/>&nbsp;&nbsp;if&nbsp;(id&nbsp;!==&nbsp;rtc.params.uid)&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;rtc.client.subscribe(remoteStream,&nbsp;function&nbsp;(err)&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;stream&nbsp;subscribe&nbsp;failed&quot;,&nbsp;err);<br/>&nbsp;&nbsp;&nbsp;&nbsp;})<br/>&nbsp;&nbsp;}<br/>&nbsp;&nbsp;console.log('stream-added&nbsp;remote-uid:&nbsp;',&nbsp;id);<br/>});<br/></code></pre><ol start="2"><li>监听 “stream-subscribed” 事件,订阅成功后播放远端流。</li></ol><pre><code>rtc.client.on(&quot;stream-subscribed&quot;,&nbsp;function&nbsp;(evt)&nbsp;{<br/>&nbsp;&nbsp;var&nbsp;remoteStream&nbsp;=&nbsp;evt.stream;<br/>&nbsp;&nbsp;var&nbsp;id&nbsp;=&nbsp;remoteStream.getId();<br/>&nbsp;&nbsp;//&nbsp;Add&nbsp;a&nbsp;view&nbsp;for&nbsp;the&nbsp;remote&nbsp;stream.<br/>&nbsp;&nbsp;addView(id);<br/>&nbsp;&nbsp;//&nbsp;Play&nbsp;the&nbsp;remote&nbsp;stream.<br/>&nbsp;&nbsp;remoteStream.play(&quot;remote_video_&quot;&nbsp;+&nbsp;id);<br/>&nbsp;&nbsp;console.log('stream-subscribed&nbsp;remote-uid:&nbsp;',&nbsp;id);<br/>})<br/></code></pre><p>受浏览器策略影响,在 Chrome 70+ 和 Safari 浏览器上,Stream.play 方法必须由用户手势触发,详情请在声网文档中心搜索、参考 Autoplay Policy Changes。<br/>3. 监听 “stream-removed” 事件,当远端流被移除时(例如远端用户调用了 Stream.unpublish), 停止播放该流并移除它的画面。</p><pre><code>rtc.client.on(&quot;stream-removed&quot;,&nbsp;function&nbsp;(evt)&nbsp;{<br/>&nbsp;&nbsp;var&nbsp;remoteStream&nbsp;=&nbsp;evt.stream;<br/>&nbsp;&nbsp;var&nbsp;id&nbsp;=&nbsp;remoteStream.getId();<br/>&nbsp;&nbsp;//&nbsp;Stop&nbsp;playing&nbsp;the&nbsp;remote&nbsp;stream.<br/>&nbsp;&nbsp;remoteStream.stop(&quot;remote_video_&quot;&nbsp;+&nbsp;id);<br/>&nbsp;&nbsp;//&nbsp;Remove&nbsp;the&nbsp;view&nbsp;of&nbsp;the&nbsp;remote&nbsp;stream.&nbsp;<br/>&nbsp;&nbsp;removeView(id);<br/>&nbsp;&nbsp;console.log('stream-removed&nbsp;remote-uid:&nbsp;',&nbsp;id);<br/>})<br/></code></pre><p>你需要自己实现 addView 和 removeView 的功能,可以参考以下示例代码。</p><pre><code>function&nbsp;addView&nbsp;(id,&nbsp;show)&nbsp;{<br/>&nbsp;&nbsp;if&nbsp;(!(&quot;#&quot;&nbsp;+&nbsp;id)[0])&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;(&quot;&lt;div/&gt;&quot;,&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;&quot;remote_video_panel_&quot;&nbsp;+&nbsp;id,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class:&nbsp;&quot;video-view&quot;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;}).appendTo(&quot;#video&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;(&quot;&lt;div/&gt;&quot;,&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;&quot;remote_video_&quot;&nbsp;+&nbsp;id,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class:&nbsp;&quot;video-placeholder&quot;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;}).appendTo(&quot;#remote_video_panel_&quot;&nbsp;+&nbsp;id);<br/>&nbsp;&nbsp;&nbsp;&nbsp;(&quot;&lt;div/&gt;&quot;,&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;&quot;remote_video_info_&quot;&nbsp;+&nbsp;id,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class:&nbsp;&quot;video-profile&nbsp;&quot;&nbsp;+&nbsp;(show&nbsp;?&nbsp;&quot;&quot;&nbsp;:&nbsp;&nbsp;&quot;hide&quot;),<br/>&nbsp;&nbsp;&nbsp;&nbsp;}).appendTo(&quot;#remote_video_panel_&quot;&nbsp;+&nbsp;id);<br/>&nbsp;&nbsp;&nbsp;&nbsp;(&quot;&lt;div/&gt;&quot;,&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;&quot;video_autoplay_&quot;+&nbsp;id,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class:&nbsp;&quot;autoplay-fallback&nbsp;hide&quot;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;}).appendTo(&quot;#remote_video_panel_&quot;&nbsp;+&nbsp;id);<br/>&nbsp;&nbsp;}<br/>}<br/>function&nbsp;removeView&nbsp;(id)&nbsp;{<br/>&nbsp;&nbsp;if&nbsp;((&quot;#remote_video_panel_&quot;&nbsp;+&nbsp;id)[0])&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#remote_video_panel_&quot;+id).remove();<br/>&nbsp;&nbsp;}<br/>}<br/></code></pre><h3>离开频道</h3><p>调用 Client.leave 方法离开频道。</p><pre><code>//&nbsp;Leave&nbsp;the&nbsp;channel<br/>rtc.client.leave(function&nbsp;()&nbsp;{<br/>&nbsp;&nbsp;//&nbsp;Stop&nbsp;playing&nbsp;the&nbsp;local&nbsp;stream<br/>&nbsp;&nbsp;rtc.localStream.stop();<br/>&nbsp;&nbsp;//&nbsp;Close&nbsp;the&nbsp;local&nbsp;stream<br/>&nbsp;&nbsp;rtc.localStream.close();<br/>&nbsp;&nbsp;//&nbsp;Stop&nbsp;playing&nbsp;the&nbsp;remote&nbsp;streams&nbsp;and&nbsp;remove&nbsp;the&nbsp;views<br/>&nbsp;&nbsp;while&nbsp;(rtc.remoteStreams.length&nbsp;&gt;&nbsp;0)&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;stream&nbsp;=&nbsp;rtc.remoteStreams.shift();<br/>&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;id&nbsp;=&nbsp;stream.getId();<br/>&nbsp;&nbsp;&nbsp;&nbsp;stream.stop();<br/>&nbsp;&nbsp;&nbsp;&nbsp;removeView(id);<br/>&nbsp;&nbsp;}<br/>&nbsp;&nbsp;console.log(&quot;client&nbsp;leaves&nbsp;channel&nbsp;success&quot;);<br/>},&nbsp;function&nbsp;(err)&nbsp;{<br/>&nbsp;&nbsp;console.log(&quot;channel&nbsp;leave&nbsp;failed&quot;);<br/>&nbsp;&nbsp;console.error(err);<br/>})<br/><br/></code></pre><h3>运行你的 app</h3><p>我们建议在本地 Web 服务器上测试你的 app。这里我们用 npm 的 live-server 设置一个本地服务器。</p><p>在本地服务器(localhost)运行 web app 仅作为测试用途。部署生产环境时,请确保使用 HTTPS 协议。</p><ol><li>安装 live-server。</li></ol><pre><code>npm&nbsp;i&nbsp;live-server&nbsp;-g<br/></code></pre><ol start="2"><li><p>在命令行中进入你的项目所在的目录。</p></li><li><p>运行 app。</p></li></ol><pre><code>live-server&nbsp;.<br/></code></pre><p>现在你的浏览器应该会自动打开你的 web app 页面。</p><ol start="4"><li><p>输入频道名,选择用户角色,点击 JOIN 开始通话。<br/>你可能需要给浏览器摄像头和麦克风权限。如果在创建本地流时打开了视频且选择主播角色,你现在应该可以看到自己的视频画面。</p></li><li><p>在浏览器中打开另一个页面,输入相同的 URL 地址。点击 JOIN 按钮。现在你应该可以看到两个视频画面。</p></li></ol><p>如果页面没有正常工作,可以打开浏览器的控制台查看错误信息进行排查。常见的错误信息包括:</p><ul><li><p>INVALID_VENDOR_KEY:App ID 错误,检查你填写的 App ID。</p></li><li><p>ERR_DYNAMIC_USE_STATIC_KE:你的 Agora 项目启用了 App 证书,需要在加入频道时填写 Token。</p></li><li><p>Media access:NotFoundError:检查你的摄像头和麦克风是否正常工作。</p></li><li><p>MEDIA_NOT_SUPPORT:请使用 HTTPS 协议 或者 localhost。</p></li></ul><p><strong>本文转载自 声网 Agora 公众号。</strong></p><p><strong>原文链接:</strong><a href="https://mp.weixin.qq.com/s/bK6bwE4rPXGFNx7sfAftrA">https://mp.weixin.qq.com/s/bK6bwE4rPXGFNx7sfAftrA</a></p>


2020-02-26 15:50900

评论

发布
暂无评论
发现更多内容

FastApi-02-路径参数

Python研究所

FastApi 8月日更

京东:Flink SQL 优化实战

Apache Flink

flink

Java开发前景怎么样?【Spring Boot 21

策划Java工程师

Java 程序员 后端

全国首笔“区块链+闲置住宅”交易在昆山完成

CECBC

亏损、退市、卖身...区块链如何挽救影视行业?

CECBC

双非本科电子跨专业,苦学八个月,投岗阿里/滴滴后端三面,最终拿下offer

今晚早点睡

Java 阿里巴巴 面试 计算机

GitHub标星过万!亦直问JVM(1)

Java 程序员 后端

Java大厂技术面试题汇总!美团阿里Java程序员晒工资被围观,总结

Java 程序员 后端

Java开发6年了,BAT面试文档:ActiveMQ(1)

策划Java工程师

Java 程序员 后端

区块链的兴起及其司法运用

CECBC

IBM大面积辞退40岁+的员工,【Spring Boot 1

Java 程序员 后端

TimeUtils 实用封装

Changing Lin

8月日更

Java开发三年月薪才12K,你知道如何用面向对象思想写好并发编程吗?

策划Java工程师

Java 程序员 后端

TCL携大屏天团领跑UDE,斩获多项创新大奖

科技热闻

Java体系化进阶学习图谱:所有帖子的 分类 总结

Java 程序员 后端

Java入门你值得拥有!【Spring Boot 26

Java 程序员 后端

AI应用说 | 百度专家&行业大咖畅谈AI技术与落地应用

百度大脑

人工智能 开发者 开发

Java开发入门教程!程序员:面试官

策划Java工程师

Java 程序员 后端

Java开发全套学习!MySQL进阶,秒变大神(1)

策划Java工程师

Java 程序员 后端

毕业总结

Vincent

架构训练营

Java开发基础面试题,【springcloud

策划Java工程师

Java 程序员 后端

Java开发快速学习!三面蚂蚁金服成功拿到offer后,他说他累了

策划Java工程师

Java 程序员 后端

应届生怎么走Linux下C++后台服务器开发路线,工作3-5年的知识体系

Linux服务器开发

Linux C/C++ linux开发 Linux服务器开发 Linux后台开发

Java开发从零开始!《SpringCloud超级入门(4)

策划Java工程师

Java 程序员 后端

IT公司防止运维偷窥和篡改数据库的最佳武器-云堡垒机!

行云管家

数据安全 堡垒机 数据泄露

架构实战营毕业总结

eoeoeo

架构实战营

Java基础72问:不搞定HR这3个问题,建议不要轻易跳槽(1)

Java 程序员 后端

Java应用性能优化!Java-进阶:集合框架1

Java 程序员 后端

Java开发基础不牢?什么是中间件?

策划Java工程师

Java 程序员 后端

终于有人把操作系统,网络系统,线程进程,IO模型全部总结出来了

程序员 架构 面试 操作系统 计算机

架构实战营模块3作业指导

华仔

架构实战营

基于 Agora SDK 实现 Web 端的多人视频互动_行业深度_声网_InfoQ精选文章