使用 SimpleWebRTC 构建 WebRTC 视频聊天应用程序

Building a WebRTC Video Chat Application with SimpleWebRTC 机翻

原文:Building a WebRTC Video Chat Application with SimpleWebRTC - SitePoint

随着 WebRTC 的出现以及浏览器实时处理对等通信的能力不断提高,构建实时应用程序比以往任何时候都容易。在本教程中,我们将了解SimpleWebRTC以及它如何在实现 WebRTC 时让我们的生活更轻松。在整篇文章中,我们将构建一个具有消息传递功能的 WebRTC 视频聊天应用程序。

如果您需要一些关于 WebRTC 和点对点通信的背景知识,我建议您阅读WebRTC 的黎明getUserMedia API 简介

什么是 SimpleWebRTC

在我们继续之前,重要的是我们了解我们将使用的主要工具。SimpleWebRTC是一个 JavaScript 库,可简化 WebRTC 点对点数据、视频和音频调用。

SimpleWebRTC 充当浏览器的 WebRTC 实现的包装器。您可能已经知道,浏览器供应商并不完全同意实现不同功能的单一方式,这意味着对于每个浏览器,WebRTC 都有不同的实现。作为开发人员,您必须为计划支持的每个浏览器编写不同的代码。SimpleWebRT 充当该代码的包装器。它公开的 API 易于使用和理解,这使其成为实现跨浏览器 WebRTC 的绝佳候选者。

构建 WebRTC 视频聊天应用

现在是时候通过构建应用程序来弄脏我们的手了。我们将构建一个运行在 Express 服务器之上的单页应用程序。

请注意,您可以从我们的GitHub 存储库下载本教程的代码。要运行它,或者在家里跟随它,你需要安装 Node 和 npm。如果您不熟悉这些,或者需要一些帮助来安装它们,请查看我们之前的教程:

您还需要一台带有网络摄像头的 PC 或笔记本电脑。如果没有,您需要为自己准备一个可以连接到显示器顶部的 USB 网络摄像头。您可能需要朋友或第二台设备来测试远程连接。

依赖项

我们将使用以下依赖项来构建我们的项目:

  • SimpleWebRTC — WebRTC 库
  • Semantic UI CSS — 一个优雅的 CSS 框架
  • jQuery — 用于选择页面上的元素和事件处理。
  • Handlebars — 一个 JavaScript 模板库,我们将使用它为消息生成 HTML
  • Express — NodeJS 服务器。

项目设置

转到您的工作区并创建一个文件夹simplewebrtc-messenger。在 VSCode 或您喜欢的编辑器中打开文件夹并创建以下文件和文件夹结构:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash">simplewebrtc-messenger
├── public
│   ├── images
│   │   └── image.png
│   ├── index.html
│   └── js
│       └── app.js
├── README.md
└── server.js
</code></span></span>

或者,如果您愿意,也可以通过命令行执行相同操作:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash"><span style="color:#82aaff">mkdir</span> -p simplewebrtc-messenger/public/<span style="color:#c792ea">{</span>images,js<span style="color:#c792ea">}</span>
<span style="color:#ffcb6b">cd</span> simplewebrtc-messenger
<span style="color:#82aaff">touch</span> public/js/app.js public/index.html .gitignore README.md server.js
</code></span></span>

打开README.md并复制以下内容:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-md"><span style="color:#ee9900"><strong><span style="color:#c792ea">#</span> Simple WebRTC Messenger</strong></span>

A tutorial on building a WebRTC video chat app using SimpleWebRTC.
</code></span></span>

如果您打算使用 git 存储库,请将该行添加node_modules到文件中。使用以下命令.gitignore生成文件:package.json

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash"><span style="color:#82aaff">npm</span> init -y
</code></span></span>

您应该得到以下输出:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#c792ea">{</span>
  <span style="color:#c3e88d">"name"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"simplewebrtc-messenger"</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"version"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"1.0.0"</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"description"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"A tutorial on building a WebRTC video chat app using SimpleWebRTC."</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"main"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"server.js"</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"scripts"</span><span style="color:#89ddff">:</span> <span style="color:#c792ea">{</span>
    <span style="color:#c3e88d">"test"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"echo \"Error: no test specified\" && exit 1"</span><span style="color:#c792ea">,</span>
    <span style="color:#c3e88d">"start"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"node server.js"</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"keywords"</span><span style="color:#89ddff">:</span> <span style="color:#c792ea">[</span><span style="color:#c792ea">]</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"author"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">""</span><span style="color:#c792ea">,</span>
  <span style="color:#c3e88d">"license"</span><span style="color:#89ddff">:</span> <span style="color:#c3e88d">"ISC"</span>
<span style="color:#c792ea">}</span>
</code></span></span>

现在让我们安装我们的依赖项:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash"><span style="color:#82aaff">npm</span> <span style="color:#82aaff">install</span> express handlebars jquery semantic-ui-css simplewebrtc
</code></span></span>

随着安装的进行,将此代码复制到server.js

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript">const express <span style="color:#89ddff">=</span> <span style="color:#82aaff">require</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'express'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

const app <span style="color:#89ddff">=</span> <span style="color:#82aaff">express</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const port <span style="color:#89ddff">=</span> <span style="color:#f78c6c">3000</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Set public folder as root</span>
app<span style="color:#c792ea">.</span><span style="color:#82aaff">use</span><span style="color:#c792ea">(</span>express<span style="color:#c792ea">.</span><span style="color:#82aaff">static</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'public'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Provide access to node_modules folder from the client-side</span>
app<span style="color:#c792ea">.</span><span style="color:#82aaff">use</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'/scripts'</span><span style="color:#c792ea">,</span> express<span style="color:#c792ea">.</span><span style="color:#82aaff">static</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">${</span>__dirname<span style="color:#c792ea">}</span><span style="color:#c3e88d">/node_modules/</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Redirect all traffic to index.html</span>
app<span style="color:#c792ea">.</span><span style="color:#82aaff">use</span><span style="color:#c792ea">(</span><span style="color:#c792ea">(</span>req<span style="color:#c792ea">,</span> res<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> res<span style="color:#c792ea">.</span><span style="color:#82aaff">sendFile</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">${</span>__dirname<span style="color:#c792ea">}</span><span style="color:#c3e88d">/public/index.html</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

app<span style="color:#c792ea">.</span><span style="color:#82aaff">listen</span><span style="color:#c792ea">(</span>port<span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span><span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  <span style="color:#ffcb6b">console</span><span style="color:#c792ea">.</span><span style="color:#82aaff">info</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'listening on %d'</span><span style="color:#c792ea">,</span> port<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

服务器代码非常标准。只需阅读评论以了解发生了什么。

接下来,让我们设置我们的public/index.html文件:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-markup"><span style="color:#c792ea"><span style="color:#c792ea"><!</span>DOCTYPE html<span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>html</span> <span style="color:#ffcb6b">lang</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>en<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>head</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>meta</span> <span style="color:#ffcb6b">charset</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>UTF-8<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>meta</span> <span style="color:#ffcb6b">name</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>viewport<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">content</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>width=device-width, initial-scale=1.0<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>meta</span> <span style="color:#ffcb6b">http-equiv</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>X-UA-Compatible<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">content</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ie=edge<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>link</span> <span style="color:#ffcb6b">rel</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>stylesheet<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">href</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>scripts/semantic-ui-css/semantic.min.css<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>title</span><span style="color:#c792ea">></span></span>SimpleWebRTC Demo<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>title</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>style</span><span style="color:#c792ea">></span></span>
    <span style="color:#c792ea">html</span> <span style="color:#c792ea">{</span> margin-top<span style="color:#c792ea">:</span> <span style="color:#f78c6c">20</span>px<span style="color:#c792ea">;</span> <span style="color:#c792ea">}</span>
    <span style="color:#c792ea">#chat-content</span> <span style="color:#c792ea">{</span> height<span style="color:#c792ea">:</span> <span style="color:#f78c6c">180</span>px<span style="color:#c792ea">;</span>  overflow-y<span style="color:#c792ea">:</span> scroll<span style="color:#c792ea">;</span> <span style="color:#c792ea">}</span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>style</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>head</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>body</span><span style="color:#c792ea">></span></span>
  <span style="color:#697098"><!-- Main Content --></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui container<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>h1</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui header<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>Simple WebRTC Messenger<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>h1</span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>hr</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>

  <span style="color:#697098"><!-- Scripts --></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>scripts/jquery/dist/jquery.min.js<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>scripts/semantic-ui-css/semantic.min.js<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>scripts/handlebars/dist/handlebars.min.js <span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>scripts/simplewebrtc/out/simplewebrtc-with-adapter.bundle.js<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>js/app.js<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>body</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>html</span><span style="color:#c792ea">></span></span>
</code></span></span>

接下来,让我们设置我们的基本客户端 JavaScript 代码。将此代码复制到public/js/app.js

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#bfc7d5">window</span><span style="color:#c792ea">.</span><span style="color:#82aaff">addEventListener</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'load'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span><span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  <span style="color:#697098">// Put all client-side code here</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

最后,从我们的 GitHub 存储库下载此图像并将其保存在public/images文件夹中。

现在我们可以运行我们的应用程序了:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash"><span style="color:#82aaff">npm</span> start
</code></span></span>

在浏览器中打开 URL localhost:3000,您应该会看到以下内容:

标记

现在让我们继续public/index.html。为了简单起见(特别是如果您已经熟悉 Handlebars),您可以从我们的GitHub 存储库中复制整个标记代码。否则,让我们一步一步来。首先,复制此代码并将其放在div中的<hr>标记之后:ui container

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-markup"><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui two column stackable grid<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>

  <span style="color:#697098"><!-- Chat Section --></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui ten wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui segment<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
      <span style="color:#697098"><!-- Chat Room Form --></span>
      <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui form<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
        <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>fields<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>field<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
            <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>label</span><span style="color:#c792ea">></span></span>User Name<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>label</span><span style="color:#c792ea">></span></span>
            <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>input</span> <span style="color:#ffcb6b">type</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>text<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">placeholder</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>Enter user name<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>username<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">name</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>username<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>field<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
            <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>label</span><span style="color:#c792ea">></span></span>Room<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>label</span><span style="color:#c792ea">></span></span>
            <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>input</span> <span style="color:#ffcb6b">type</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>text<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">placeholder</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>Enter room name<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>roomName<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">name</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>roomName<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
        <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
        <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>br</span><span style="color:#c792ea">></span></span>
        <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui buttons<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>create-btn<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui submit orange button<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>Create Room<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>or<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
          <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>join-btn<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui submit green button<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>Join Room<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
        <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
      <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
      <span style="color:#697098"><!-- Chat Room Messages --></span>
      <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>chat<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
  <span style="color:#697098"><!-- End of Chat Section --></span>

  <span style="color:#697098"><!-- Local Camera --></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui six wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>h4</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui center aligned header<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">style</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>margin<span style="color:#c792ea">:</span><span style="color:#f78c6c">0</span><span style="color:#c792ea">;</span><span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
      Local Camera
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>h4</span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>img</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>local-image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui large image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>images/image.png<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>video</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>local-video<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui large image hidden<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">autoplay</span><span style="color:#c792ea">></span></span><span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>video</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>

<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>

<span style="color:#697098"><!-- Remote Cameras --></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>h3</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui center aligned header<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>Remote Cameras<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>h3</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>remote-videos<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui stackable grid<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>four wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>img</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui centered medium image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>images/image.png<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>four wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>img</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui centered medium image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>images/image.png<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>four wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>img</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui centered medium image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>images/image.png<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>div</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>four wide column<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
    <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>img</span> <span style="color:#ffcb6b">class</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>ui centered medium image<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">src</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>images/image.png<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>div</span><span style="color:#c792ea">></span></span>
</code></span></span>

浏览标记代码并阅读注释以了解每个部分的用途。如果您不熟悉 CSS 库,还可以查看Semantic UI文档。刷新您的浏览器。您应该有以下视图:

我们使用空白图像作为占位符来指示相机位置将流到网页上的哪个位置。请注意,只要您的互联网带宽可以处理,此应用程序将能够支持多个远程连接。

模板

现在让我们添加三个 Handlebar 模板,这将使我们的网页具有交互性。

在 div 之后放置以下标记ui container(尽管位置并不重要)。我们将从聊天容器开始,它由以下部分组成:

  • 房间号
  • 空聊天消息容器(稍后通过 JavaScript 填充)
  • 用于发布消息的输入。
<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-markup"><span style="color:#697098"><!-- Chat Template --></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>chat-template<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">type</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>text/x-handlebars-template<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#89ddff"><</span>h3 class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"ui orange header"</span><span style="color:#89ddff">></span>Room <span style="color:#82aaff">ID</span> <span style="color:#89ddff">-</span><span style="color:#89ddff">></span> <span style="color:#89ddff"><</span>strong<span style="color:#89ddff">></span><span style="color:#c792ea">{</span><span style="color:#c792ea">{</span> room <span style="color:#c792ea">}</span><span style="color:#c792ea">}</span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>strong<span style="color:#89ddff">></span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>h3<span style="color:#89ddff">></span>
  <span style="color:#89ddff"><</span>hr<span style="color:#89ddff">></span>
  <span style="color:#89ddff"><</span>div id<span style="color:#89ddff">=</span><span style="color:#c3e88d">"chat-content"</span> class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"ui feed"</span><span style="color:#89ddff">></span> <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
  <span style="color:#89ddff"><</span>hr<span style="color:#89ddff">></span>
  <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"ui form"</span><span style="color:#89ddff">></span>
    <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"ui field"</span><span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span>label<span style="color:#89ddff">></span>Post Message<span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>label<span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span>textarea id<span style="color:#89ddff">=</span><span style="color:#c3e88d">"post-message"</span> name<span style="color:#89ddff">=</span><span style="color:#c3e88d">"post-message"</span> rows<span style="color:#89ddff">=</span><span style="color:#c3e88d">"1"</span><span style="color:#89ddff">></span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>textarea<span style="color:#89ddff">></span>
    <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
    <span style="color:#89ddff"><</span>div id<span style="color:#89ddff">=</span><span style="color:#c3e88d">"post-btn"</span> class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"ui primary submit button"</span><span style="color:#89ddff">></span>Send<span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
  <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
</code></span></span>

接下来,添加以下模板,该模板将用于显示用户聊天消息:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-markup"><span style="color:#697098"><!-- Chat Content Template --></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>chat-content-template<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">type</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>text/x-handlebars-template<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#c792ea">{</span><span style="color:#c792ea">{</span>#each messages<span style="color:#c792ea">}</span><span style="color:#c792ea">}</span>
    <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"event"</span><span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"label"</span><span style="color:#89ddff">></span>
        <span style="color:#89ddff"><</span>i class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"icon blue user"</span><span style="color:#89ddff">></span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>i<span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"content"</span><span style="color:#89ddff">></span>
        <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"summary"</span><span style="color:#89ddff">></span>
          <span style="color:#89ddff"><</span>a href<span style="color:#89ddff">=</span><span style="color:#c3e88d">"#"</span><span style="color:#89ddff">></span> <span style="color:#c792ea">{</span><span style="color:#c792ea">{</span> username <span style="color:#c792ea">}</span><span style="color:#c792ea">}</span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>a<span style="color:#89ddff">></span> posted on
          <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"date"</span><span style="color:#89ddff">></span>
            <span style="color:#c792ea">{</span><span style="color:#c792ea">{</span> postedOn <span style="color:#c792ea">}</span><span style="color:#c792ea">}</span>
          <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
        <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
        <span style="color:#89ddff"><</span>div class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"extra text"</span><span style="color:#89ddff">></span>
          <span style="color:#c792ea">{</span><span style="color:#c792ea">{</span> message <span style="color:#c792ea">}</span><span style="color:#c792ea">}</span>
        <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
      <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
    <span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
  <span style="color:#c792ea">{</span><span style="color:#c792ea">{</span><span style="color:#89ddff">/</span>each<span style="color:#c792ea">}</span><span style="color:#c792ea">}</span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
</code></span></span>

最后,添加以下模板,该模板将用于显示来自远程摄像机的流:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-markup"><span style="color:#697098"><!-- Remote Video Template --></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"><</span>script</span> <span style="color:#ffcb6b">id</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>remote-video-template<span style="color:#c792ea">"</span></span> <span style="color:#ffcb6b">type</span><span style="color:#ff5572"><span style="color:#c792ea">=</span><span style="color:#c792ea">"</span>text/x-handlebars-template<span style="color:#c792ea">"</span></span><span style="color:#c792ea">></span></span>
  <span style="color:#89ddff"><</span>div id<span style="color:#89ddff">=</span><span style="color:#c3e88d">"{{ id }}"</span> class<span style="color:#89ddff">=</span><span style="color:#c3e88d">"four wide column"</span><span style="color:#89ddff">></span><span style="color:#89ddff"><</span><span style="color:#89ddff">/</span>div<span style="color:#89ddff">></span>
<span style="color:#ff5572"><span style="color:#ff5572"><span style="color:#c792ea"></</span>script</span><span style="color:#c792ea">></span></span>
</code></span></span>

标记代码希望是不言自明的,所以让我们继续为我们的应用程序编写客户端 JavaScript 代码。

主应用脚本

打开文件public/js/app.js并添加以下代码:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Chat platform</span>
const chatTemplate <span style="color:#89ddff">=</span> Handlebars<span style="color:#c792ea">.</span><span style="color:#82aaff">compile</span><span style="color:#c792ea">(</span><span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#chat-template'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const chatContentTemplate <span style="color:#89ddff">=</span> Handlebars<span style="color:#c792ea">.</span><span style="color:#82aaff">compile</span><span style="color:#c792ea">(</span><span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#chat-content-template'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const chatEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#chat'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const formEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'.form'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const messages <span style="color:#89ddff">=</span> <span style="color:#c792ea">[</span><span style="color:#c792ea">]</span><span style="color:#c792ea">;</span>
let username<span style="color:#c792ea">;</span>

<span style="color:#697098">// Local Video</span>
const localImageEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#local-image'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const localVideoEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#local-video'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Remote Videos</span>
const remoteVideoTemplate <span style="color:#89ddff">=</span> Handlebars<span style="color:#c792ea">.</span><span style="color:#82aaff">compile</span><span style="color:#c792ea">(</span><span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#remote-video-template'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
const remoteVideosEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#remote-videos'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
let remoteVideosCount <span style="color:#89ddff">=</span> <span style="color:#f78c6c">0</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Add validation rules to Create/Join Room Form</span>
formEl<span style="color:#c792ea">.</span><span style="color:#82aaff">form</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span>
  fields<span style="color:#89ddff">:</span> <span style="color:#c792ea">{</span>
    roomName<span style="color:#89ddff">:</span> <span style="color:#c3e88d">'empty'</span><span style="color:#c792ea">,</span>
    username<span style="color:#89ddff">:</span> <span style="color:#c3e88d">'empty'</span><span style="color:#c792ea">,</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">,</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

在这里,我们正在初始化我们计划操作的几个元素。我们还在表单中添加了验证规则,以便用户不能将任何一个字段留空。

接下来,让我们初始化我们的 WebRTC 代码:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// create our WebRTC connection</span>
const webrtc <span style="color:#89ddff">=</span> new <span style="color:#ffcb6b">SimpleWebRTC</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span>
  <span style="color:#697098">// the id/element dom element that will hold "our" video</span>
  localVideoEl<span style="color:#89ddff">:</span> <span style="color:#c3e88d">'local-video'</span><span style="color:#c792ea">,</span>
  <span style="color:#697098">// the id/element dom element that will hold remote videos</span>
  remoteVideosEl<span style="color:#89ddff">:</span> <span style="color:#c3e88d">'remote-videos'</span><span style="color:#c792ea">,</span>
  <span style="color:#697098">// immediately ask for camera access</span>
  autoRequestMedia<span style="color:#89ddff">:</span> <span style="color:#ff5874">true</span><span style="color:#c792ea">,</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// We got access to local camera</span>
webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'localStream'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span><span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  localImageEl<span style="color:#c792ea">.</span><span style="color:#82aaff">hide</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  localVideoEl<span style="color:#c792ea">.</span><span style="color:#82aaff">show</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

现在你知道为什么它被称为 SimpleWebRTC。这就是我们初始化 WebRTC 代码所需要做的一切。请注意,我们甚至没有指定任何 ICE 服务器或 STUN 服务器。它只是工作。但是,您可以使用其他 TURN 服务,例如Xirsys。您需要设置一个本地SignalMaster服务器来处理 WebRTC 信号。

让我们快速刷新一下网页以确认新代码正在运行:

该页面应请求访问您的相机和麦克风。只需单击接受,您应该会得到上面的视图。

聊天室脚本

现在让我们使表单功能化。我们需要编写创建和加入房间的逻辑。此外,我们需要编写额外的逻辑来显示聊天室。我们将chat-room-template为此使用 。让我们首先将点击处理程序附加到表单的按钮:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'.submit'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'click'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span>event<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  if <span style="color:#c792ea">(</span><span style="color:#89ddff">!</span>formEl<span style="color:#c792ea">.</span><span style="color:#82aaff">form</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'is valid'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">)</span> <span style="color:#c792ea">{</span>
    return <span style="color:#ff5874">false</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span>
  username <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#username'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">val</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  const roomName <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#roomName'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">val</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">toLowerCase</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  if <span style="color:#c792ea">(</span>event<span style="color:#c792ea">.</span>target<span style="color:#c792ea">.</span>id <span style="color:#89ddff">===</span> <span style="color:#c3e88d">'create-btn'</span><span style="color:#c792ea">)</span> <span style="color:#c792ea">{</span>
    <span style="color:#82aaff">createRoom</span><span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span> else <span style="color:#c792ea">{</span>
    <span style="color:#82aaff">joinRoom</span><span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span>
  return <span style="color:#ff5874">false</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

接下来,我们需要声明createRoomandjoinRoom函数。将以下代码放在点击处理程序代码之前:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Register new Chat Room</span>
const <span style="color:#82aaff">createRoom</span> <span style="color:#89ddff">=</span> <span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  <span style="color:#ffcb6b">console</span><span style="color:#c792ea">.</span><span style="color:#82aaff">info</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c3e88d">Creating new room: </span><span style="color:#c792ea">${</span>roomName<span style="color:#c792ea">}</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">createRoom</span><span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span>err<span style="color:#c792ea">,</span> name<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
    <span style="color:#82aaff">showChatRoom</span><span style="color:#c792ea">(</span>name<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
    <span style="color:#82aaff">postMessage</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">${</span>username<span style="color:#c792ea">}</span><span style="color:#c3e88d"> created chatroom</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Join existing Chat Room</span>
const <span style="color:#82aaff">joinRoom</span> <span style="color:#89ddff">=</span> <span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  <span style="color:#ffcb6b">console</span><span style="color:#c792ea">.</span><span style="color:#82aaff">log</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c3e88d">Joining Room: </span><span style="color:#c792ea">${</span>roomName<span style="color:#c792ea">}</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">joinRoom</span><span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">showChatRoom</span><span style="color:#c792ea">(</span>roomName<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">postMessage</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">${</span>username<span style="color:#c792ea">}</span><span style="color:#c3e88d"> joined chatroom</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>
</code></span></span>

创建或加入房间就这么简单:只需使用SimpleWebRTC 的 createRoom 和 joinRoom 方法

您可能还注意到我们还有尚未定义的功能showChatroompostMessage现在让我们通过在调用代码之前插入以下代码来做到这一点:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Post Local Message</span>
const <span style="color:#82aaff">postMessage</span> <span style="color:#89ddff">=</span> <span style="color:#c792ea">(</span>message<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  const chatMessage <span style="color:#89ddff">=</span> <span style="color:#c792ea">{</span>
    username<span style="color:#c792ea">,</span>
    message<span style="color:#c792ea">,</span>
    postedOn<span style="color:#89ddff">:</span> new <span style="color:#ffcb6b">Date</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">toLocaleString</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'en-GB'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">,</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>
  <span style="color:#697098">// Send to all peers</span>
  webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">sendToAll</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'chat'</span><span style="color:#c792ea">,</span> chatMessage<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#697098">// Update messages locally</span>
  messages<span style="color:#c792ea">.</span><span style="color:#82aaff">push</span><span style="color:#c792ea">(</span>chatMessage<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#post-message'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">val</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">''</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">updateChatMessages</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>

<span style="color:#697098">// Display Chat Interface</span>
const <span style="color:#82aaff">showChatRoom</span> <span style="color:#89ddff">=</span> <span style="color:#c792ea">(</span>room<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  <span style="color:#697098">// Hide form</span>
  formEl<span style="color:#c792ea">.</span><span style="color:#82aaff">hide</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  const html <span style="color:#89ddff">=</span> <span style="color:#82aaff">chatTemplate</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span> room <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  chatEl<span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span>html<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  const postForm <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'form'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#697098">// Post Message Validation Rules</span>
  postForm<span style="color:#c792ea">.</span><span style="color:#82aaff">form</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span>
    message<span style="color:#89ddff">:</span> <span style="color:#c3e88d">'empty'</span><span style="color:#c792ea">,</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#post-btn'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'click'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span><span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
    const message <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#post-message'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">val</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
    <span style="color:#82aaff">postMessage</span><span style="color:#c792ea">(</span>message<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#post-message'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'keyup'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span>event<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
    if <span style="color:#c792ea">(</span>event<span style="color:#c792ea">.</span>keyCode <span style="color:#89ddff">===</span> <span style="color:#f78c6c">13</span><span style="color:#c792ea">)</span> <span style="color:#c792ea">{</span>
      const message <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#post-message'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">val</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
      <span style="color:#82aaff">postMessage</span><span style="color:#c792ea">(</span>message<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
    <span style="color:#c792ea">}</span>
  <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>
</code></span></span>

花一些时间浏览代码以了解逻辑。你很快就会遇到另一个我们没有声明的函数,updateChatMessages. 现在让我们添加它:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Update Chat Messages</span>
const <span style="color:#82aaff">updateChatMessages</span> <span style="color:#89ddff">=</span> <span style="color:#c792ea">(</span><span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  const html <span style="color:#89ddff">=</span> <span style="color:#82aaff">chatContentTemplate</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span> messages <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  const chatContentEl <span style="color:#89ddff">=</span> <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'#chat-content'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  chatContentEl<span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span>html<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#697098">// automatically scroll downwards</span>
  const scrollHeight <span style="color:#89ddff">=</span> chatContentEl<span style="color:#c792ea">.</span><span style="color:#82aaff">prop</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'scrollHeight'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  chatContentEl<span style="color:#c792ea">.</span><span style="color:#82aaff">animate</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span> scrollTop<span style="color:#89ddff">:</span> scrollHeight <span style="color:#c792ea">}</span><span style="color:#c792ea">,</span> <span style="color:#c3e88d">'slow'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">;</span>
</code></span></span>

此功能的目的只是用新消息更新聊天 UI。我们还需要一个接收来自远程用户的消息的函数。将以下函数添加到app.js

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Receive message from remote user</span>
webrtc<span style="color:#c792ea">.</span>connection<span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'message'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span>data<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  if <span style="color:#c792ea">(</span>data<span style="color:#c792ea">.</span>type <span style="color:#89ddff">===</span> <span style="color:#c3e88d">'chat'</span><span style="color:#c792ea">)</span> <span style="color:#c792ea">{</span>
    const message <span style="color:#89ddff">=</span> data<span style="color:#c792ea">.</span>payload<span style="color:#c792ea">;</span>
    messages<span style="color:#c792ea">.</span><span style="color:#82aaff">push</span><span style="color:#c792ea">(</span>message<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
    <span style="color:#82aaff">updateChatMessages</span><span style="color:#c792ea">(</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

这就是我们让聊天室正常工作所需的所有逻辑。刷新页面并登录:

点击创建房间按钮。你会被带到这个视图。发布一些消息以确认聊天室正在运行。

确认它工作正常后,继续下一个任务。

远程摄像机

如前所述,SimpleWebRTC 支持多个对等点。以下是新用户加入房间时添加远程视频流的代码:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-javascript"><span style="color:#697098">// Remote video was added</span>
webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">on</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'videoAdded'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">(</span>video<span style="color:#c792ea">,</span> peer<span style="color:#c792ea">)</span> <span style="color:#89ddff">=></span> <span style="color:#c792ea">{</span>
  const id <span style="color:#89ddff">=</span> webrtc<span style="color:#c792ea">.</span><span style="color:#82aaff">getDomId</span><span style="color:#c792ea">(</span>peer<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  const html <span style="color:#89ddff">=</span> <span style="color:#82aaff">remoteVideoTemplate</span><span style="color:#c792ea">(</span><span style="color:#c792ea">{</span> id <span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  if <span style="color:#c792ea">(</span>remoteVideosCount <span style="color:#89ddff">===</span> <span style="color:#f78c6c">0</span><span style="color:#c792ea">)</span> <span style="color:#c792ea">{</span>
    remoteVideosEl<span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span>html<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span> else <span style="color:#c792ea">{</span>
    remoteVideosEl<span style="color:#c792ea">.</span><span style="color:#82aaff">append</span><span style="color:#c792ea">(</span>html<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#c792ea">}</span>
  <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c3e88d">#</span><span style="color:#c792ea">${</span>id<span style="color:#c792ea">}</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">html</span><span style="color:#c792ea">(</span>video<span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
  <span style="color:#82aaff">$</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">`</span><span style="color:#c3e88d">#</span><span style="color:#c792ea">${</span>id<span style="color:#c792ea">}</span><span style="color:#c3e88d"> video</span><span style="color:#c3e88d">`</span><span style="color:#c792ea">)</span><span style="color:#c792ea">.</span><span style="color:#82aaff">addClass</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'ui image medium'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span> <span style="color:#697098">// Make video element responsive</span>
  remoteVideosCount <span style="color:#89ddff">+=</span> <span style="color:#f78c6c">1</span><span style="color:#c792ea">;</span>
<span style="color:#c792ea">}</span><span style="color:#c792ea">)</span><span style="color:#c792ea">;</span>
</code></span></span>

而已。如果您期待更复杂的事情,我很抱歉。我们所做的只是简单地为 增加一个事件监听器videoAdded,它的回调接收一个video可以直接添加到 DOM 的元素。它还接收一个peer对象,其中包含有关我们的对等连接的有用信息,但在这种情况下,我们只对 DOM 元素的 ID 感兴趣。

不幸的是,如果不在 HTTPS 服务器上运行,就无法测试这段代码。理论上,您可以为您的 Express 服务器生成一个自签名证书,以便在您的内部网络中运行该应用程序。但坏消息是,如果证书不是来自受信任的机构,浏览器将不允许您访问网络摄像头。

测试上述代码最简单的解决方案是将其部署到支持 HTTPS 协议的公共服务器上。

部署

我们将要执行的这种方法是部署 NodeJS 应用程序的最简单方法之一。我们所要做的就是首先在now.sh注册一个帐户。

只需选择免费计划。您需要提供您的电子邮件地址。您还需要验证您的电子邮件地址以激活您的帐户。接下来,now在您的系统上安装 CLI 工具:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash"><span style="color:#82aaff">npm</span> <span style="color:#82aaff">install</span> -g now
</code></span></span>

安装完成后,就可以部署应用了。只需在项目文件夹的根目录执行以下命令:

<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-bash">now --public
</code></span></span>

如果这是您第一次运行该命令,系统会要求您输入您的电子邮件地址。然后,您将收到一封电子邮件,您需要使用该电子邮件来验证您的登录信息。验证完成后,您需要now --public再次执行该命令。几秒钟后,您的应用程序将在指定的 URL 启动并运行,该 URL 将在终端上打印出来。

如果您使用的是 VSCode 集成终端,只需按下ALT并单击即可在浏览器中打开 URL。

您需要允许该页面访问您的摄像头和麦克风。接下来像以前一样创建一个房间。登录后,您需要访问另一台设备,例如另一台带前置摄像头的笔记本电脑或智能手机。您也可以请有互联网连接的朋友来帮助您。只需访问相同的 URL,然后输入新的用户名和相同的房间名称。远程用户必须点击加入房间按钮。在几秒钟内,两个设备都应该连接到聊天室。如果设备没有摄像头,没关系,因为聊天功能仍然可以使用。

结论

在本教程中,您了解了 SimpleWebRTC 以及如何使用它来创建实时应用程序。具体来说,我们创建了一个消息应用程序,允许用户向远程对等方发送文本和进行视频通话。SimpleWebRTC 是一个非常棒的跨浏览器库,用于在 Web 应用程序中轻松实现 WebRTC。

不要忘记本教程中使用的代码可在 GitHub 上找到。克隆它,做一些很酷的东西,玩得开心!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
网页视频开发 webrtc ;(function () { var logger = { log: function (){}, warn: function (){}, error: function (){} }; // normalize environment var RTCPeerConnection = null, getUserMedia = null, attachMediaStream = null, reattachMediaStream = null, browser = null, webRTCSupport = true; if (navigator.mozGetUserMedia) { logger.log("This appears to be Firefox"); browser = "firefox"; // The RTCPeerConnection object. RTCPeerConnection = mozRTCPeerConnection; // The RTCSessionDescription object. RTCSessionDescription = mozRTCSessionDescription; // The RTCIceCandidate object. RTCIceCandidate = mozRTCIceCandidate; // Get UserMedia (only difference is the prefix). // Code from Adam Barth. getUserMedia = navigator.mozGetUserMedia.bind(navigator); // Attach a media stream to an element. attachMediaStream = function(element, stream) { element.mozSrcObject = stream; element.play(); }; reattachMediaStream = function(to, from) { to.mozSrcObject = from.mozSrcObject; to.play(); }; // Fake get{Video,Audio}Tracks MediaStream.prototype.getVideoTracks = function() { return []; }; MediaStream.prototype.getAudioTracks = function() { return []; }; } else if (navigator.webkitGetUserMedia) { browser = "chrome"; // The RTCPeerConnection object. RTCPeerConnection = webkitRTCPeerConnection; // Get UserMedia (only difference is the prefix). // Code from Adam Barth. getUserMedia = navigator.webkitGetUserMedia.bind(navigator); // Attach a media stream to an element. attachMediaStream = function(element, stream) { element.autoplay = true; element.src = webkitURL.createObjectURL(stream); }; reattachMediaStream = function(to, from) { to.src = from.src; }; // The representation of tracks in a stream is changed in M26. // Unify them for e

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值