创建您的第一个 WebRTC 应用程序

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 63w+ 字,讲解图 2808+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2200+ 小伙伴加入学习 ,欢迎点击围观

介绍

基于 Internet 的通信一直是大中型企业不可或缺的一部分。功能齐全且设备齐全的基于互联网的通信是通过单一平台通过视频、文本、音频或电子邮件进行通信的通信。所有通信渠道都需要不同的技术。视频和音频通信通常需要专用插件。随着 WebRTC API 形式的最新技术创新,场景完全发生了变化。

让我们谈谈我们如何着手创建我们的第一个支持音频和视频通信的 HTML WebRTC 应用程序

在开始之前,让我告诉你 WebRTC 是一个网络浏览器 API,因此要使其发挥作用,你的浏览器应该支持 WebRTC。所有 WebRTC 粉丝都会很高兴知道 Mozilla Firefox 和 Google Chrome 浏览器都支持 WebRTC。


流言四起

一些应用程序平台声称它们启用了“WebRTC”,但实际上它们只支持 getUserMedia ,而 getUserMedia 不支持其余的 RTC 组件。

因此,在开发之前仔细执行平台的重要检查。

WebRTC技术亮点

让我们仔细看看 WebRTC 应用程序 的技术期望是什么:

  1. 音频、视频或其他数据的流式传输。

  2. 获取 IP 地址和端口等网络信息。与其他 WebRTC 客户端(对等方)交换此信息以启用甚至通过 NAT 和防火墙的连接。

  3. 在错误报告、启动、会话关闭和与信令通信协调的情况下。

  4. 通过流式视频、音频或数据进行通信。

  5. 交换有关媒体和客户端功能的信息,例如分辨率和编解码器。

WebRTC通过使用下面列出的一些主要API来实现上述功能:

  1. MediaStream(又名 getUserMedia)

  2. RTCP 对等连接

  3. RTC数据通道

让我们仔细看看这些 API

1. MediaStream :getUserMedia 或 MediaStream 获取对数据流的访问权限,例如来自用户摄像头和麦克风的数据流。 MediaStream 在 Chrome、Firefox 和 Opera 中可用。 MediaSream API 表示同步的媒体流。这可以很好地解释为从摄像头和麦克风输入中获取的流具有同步的视频和音频轨道。每个 MediaStream 都有一个输入,它可能是由导航器生成的 MediaStrem。 getUserMedia() ,输出可能已传递到视频元素或 RTCPeer 连接。

您必须知道 getUserMedia() 方法需要三个参数:

    1. 约束的对象。

    2. 成功回调,如果被调用,将传递一个 MediaStream。

    3. 失败回调,如果被调用,将传递一个错误对象。

每个 MediaStream 都有一个标签,例如 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'。 getAudioTracks() getVideoTracks() 方法返回一个 MediaStreamTracks 数组。

对于 simpl.info/gum 示例, stream.getAudioTracks() 返回一个空数组(因为没有音频),假设连接了一个工作网络摄像头, stream.getVideoTracks() 返回一个 MediaStreamTrack 数组,表示来自网络摄像头的流.每个 MediaStreamTrack 都有一个种类(“视频”或“音频”)和一个标签(如“FaceTime 高清摄像头(内置)”),代表一个或多个音频或视频通道。在这种情况下,只有一个视频轨道而没有音频,但您可以很容易地想象有更多的用例:例如,从前置摄像头、后置摄像头、麦克风和“屏幕共享”获取流的聊天应用程序' 应用。

请注意:getUserMedia 也可以用作 Web Audio API 的输入节点:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

getUserMedia 也可以添加到基于 Chromium 的应用程序和扩展中。添加 audioCapture 和/或 videoCapture 权限可以在安装时仅请求和授予一次权限。此后,不会询问用户是否允许访问相机或麦克风。

同样,使用 HTTPS 的页面:只需为 getUserMedia() 授予一次权限。 Always Allow 按钮第一次显示在浏览器的信息栏中。

它总是需要为任何流数据源启用 MediaStream,而不仅仅是摄像头或麦克风。这允许从光盘或任意数据源(例如其他输入和传感器)流式传输。

请注意,getUserMedia() 必须在服务器上使用,而不是本地文件系统,否则将抛出 PERMISSION_DENIED: 1 错误。

2. RTCPeerConnection : 音频或视频通话持有加密和带宽管理的扩展。它在 Chrome(在桌面和 Android 中)、Opera(在桌面和 Android 中)以及当然在 Firefox 中也得到支持。 RTCPeerConnection 由 Chrome 和 Opera 实现为 webkitRTCPeerConnection,由 Firefox 实现为 mozRTCPeerConnection。在 simpl.info/pc 上有一个 Chromium 的 RTCPeerConnection 实现的超简单演示,在 apprtc.appspot.com 上有一个很棒的视频聊天应用程序。此应用程序使用 adapter.js,这是一种由 Google 维护的 JavaScript 填充程序,可抽象出浏览器差异和规范更改。

RTCPeerConnection 是 WebRTC 组件 ,用于处理对等点之间稳定高效的流数据通信。

让我们仔细看看 WebRTC 架构 图,它展示了 RTCPeerConnection 的作用。

从 JavaScript 的角度来看图表,您必须了解 RTCPeerConnection 保护 Web 开发人员免受无数复杂性的影响。 WebRTC 使用的编解码器和协议负责大量工作,即使在不可靠的网络上也能进行​​实时通信:

  • 丢包隐藏

  • 回声消除

  • 带宽适应性

  • 动态抖动缓冲

  • 自动增益控制

  • 降噪和抑制

  • 图片“清洁”。

让我们讨论过度信号:

2 (a) 信令:会话控制、网络和媒体信息

WebRTC 使用 RTCPeerConnection 在浏览器之间传输流数据。除此之外,它还需要一种机制来协调通信和发送控制消息。这个过程可以定义为一个信令。应该知道信令不是 RTCPeerConnection API 的一部分。 WebRTC 应用程序开发人员 可以选择他们喜欢的任何消息传递协议,例如 SIP 或 XMPP,以及适当的双工(双向)通信通道。

最后,用户会发现彼此并交换姓名等“真实世界”的详细信息。 WebRTC 客户端应用程序 交换网络信息。对等点交换有关媒体的数据,例如视频格式和分辨率。 WebRTC 客户端应用程序 遍历 NAT 网关和防火墙。

由此我们也可以理解WebRTC需要四种服务端功能:

    • 用户发现和交流。

    • 信号。

    • NAT/防火墙穿越。

    • 中继服务器以防点对点通信失败。

3. RTCDataChannel :通用数据的点对点通信。该 API 受 Chrome 25、Opera 18 和 Firefox 22 及更高版本支持。

让编码开始吧!

假设您具有相当不错的 JavaScript、HTML 和 CSS 以及 Node.JS 技术和编码技能。

让我们从编码部分开始。

第 1 步:创建一个空白的 HTML5 文档

创建一个简单的 HTML 文档。


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

第 2 步:从网络摄像头获取视频

  1. 将视频元素添加到您的页面。

  2. 将以下 JavaScript 添加到您页面上的脚本元素,以启用 getUserMedia() 来设置来自网络摄像头的视频源:

  3. 在本地测试一下


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

仔细看看我们在这里做了什么。我们首先调用 getUserMedia 使用:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

constraints 参数允许我们指定要获取的媒体,在本例中仅为视频:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

如果成功,来自网络摄像头的视频流将被设置为视频元素的来源:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

第三步:设置信令服务器并开始交换消息

真实世界的应用程序在同一页面上没有发送方和接收方 RTCPeerConnections,因此我们需要一种方法让它们通信元数据。

对于它的应用程序,我们需要一个信令服务器:一个可以在一个浏览器中运行的 WebRTC 应用程序(客户端)和另一个浏览器中的客户端之间交换消息的服务器。实际消息是字符串化的 JavaScript 对象。

在这一步中,我们将构建一个简单的 Node.js 信令服务器,使用 socket.io Node 模块和 JavaScript 库进行消息传递。 Node.js 和 socket.io 的经验会很有用,但不是关键——消息传递组件非常简单。在此示例中,服务器(Node 应用程序)是 server.js,客户端(Web 应用程序)是 index.html。

此步骤中的 Node 服务器应用程序有两个任务。

    1. 充当消息中介:

    
     function gotStream(stream) {
        window.AudioContext = window.AudioContext || window.webkitAudioContext;
        var audioContext = new AudioContext();
    
    // Create an AudioNode from the stream
    var mediaStreamSource = audioContext.createMediaStreamSource(stream);
    
    // Connect it to destination to hear yourself
    // or any other node for processing!
    mediaStreamSource.connect(audioContext.destination);
    

    }

    navigator.getUserMedia({audio:true}, gotStream);

2. 管理 WebRTC 视频聊天“房间”:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

我们简单的 WebRTC 应用程序 最多只允许两个点共享一个房间。确保安装了 Node、socket.io 和 node-static。要安装 socket.io 和 node-static,请从应用程序目录中的终端运行 Node Package Manager:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

您现在将拥有三个单独的文件,index.html、server.js 和您的主要 JavaScript 文件 main.js。他们看起来像这样。

1. main.js


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);


2.index.html


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);


3. 服务器.js


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);


要启动服务器,请从应用程序目录中的终端运行以下命令:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);


第 4 步:连接一切

现在我们要连接一切。我们将向在第 2 步中创建的视频客户端添加信号。我们还将为我们的应用程序实施 RTCPeerConnection 和 RTCDataChannel。

1. 在您的主 html 文件中添加以下代码:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);


2. 您的主要 JavaScript 文件 main.js 看起来像这样:


 function gotStream(stream) {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var audioContext = new AudioContext();
// Create an AudioNode from the stream
var mediaStreamSource = audioContext.createMediaStreamSource(stream);

// Connect it to destination to hear yourself
// or any other node for processing!
mediaStreamSource.connect(audioContext.destination);

}

navigator.getUserMedia({audio:true}, gotStream);

您已经完成了您的第一个 WebRTC 应用程序

太棒了!你做到了。您现在已经自豪地拥有了一个全新的 WebRTC 视频聊天应用程序。它对您来说可能看起来很基础,但它具有坚实的应用程序基础的所有本质。您现在可以开始添加 CSS 以使页面更具吸引力。现在你的应用程序只考虑一对一的视频聊天,因此要添加更多,你可以选择添加会议选项,如果你觉得你可以像我们一样继续启动大量的移动应用程序。 :-)

相关文章