WebRTC简介及实战应用 — 从0到1实现实时音视频聊天等功能

一、WebRTC简介

WebRTC 是由一家名为 Gobal IP Solutions,简称 GIPS 的瑞典公司开发的。Google 在 2011 年收购了 GIPS,并将其源代码开源。然后又与 IETF 和 W3C 的相关标准机构合作,以确保行业达成共识。其中:

  • Web Real-Time Communications (WEBRTC) W3C 组织:定义浏览器 API。
  • Real-Time Communication in Web-browsers (RTCWEB) IETF 标准组织:定义其所需的协议,数据,安全性等手段。

WebRTC(Web Real-Time Communication)是一项开源的技术,旨在实现实时音视频以及数据通信,而无需安装任何插件或扩展。WebRTC 允许用户之间通过 P2P(Peer-to-Peer)模式进行实时通信,减轻服务器的负担并提高通信效率。

所以,我们可以在不需要任何第三方插件的情况下,实现一个浏览器到浏览器的点对点(P2P)连接,从而进行音视频实时通信。当然,WebRTC 提供了一些 API 供我们使用,在实时音视频通信的过程中,我们主要用到以下三个:

  • getUserMedia:获取音频和视频流(MediaStream)
  • RTCPeerConnection:点对点通信
  • RTCDataChannel:数据通信

不过,虽然浏览器给我们解决了大部分音视频处理问题,但是从浏览器请求音频和视频时,我们还是需要特别注意流的大小和质量。因为即便硬件能够捕获高清质量流,CPU 和带宽也不一定可以跟上,这也是我们在建立多个对等连接时,不得不考虑的问题。

1、WebRTC基本概念

1. 基本组件

WebRTC P2P 由以下几个主要组件组成:

  1. Camera 和 AudioRecord:通过 Camera(Camera1 或 Camera2)和 AudioRecord 类访问音视频设备。处理 Android 设备的权限请求,以便访问摄像头和麦克风。
  2. PeerConnectionFactory:创建 RTCPeerConnection 和 RTCDataChannel 实例的核心类。
  3. RTCPeerConnection:实现 P2P 通信,处理音视频编解码、网络通信等。负责处理信令过程、交换媒体信息以及协调 NAT 穿透。
  4. RTCDataChannel:用于在 P2P 通信中传输非音视频数据,如文字、图片、文件等。实现低延迟、可靠的数据通信通道。
  5. VideoTrack 和 AudioTrack:代表视频轨道和音频轨道。操作音视频流,例如添加到 RTCPeerConnection 中,实现音视频的传输。
  6. VideoRenderer:用于显示远端视频流。为本地和远端视频流分别创建 VideoRenderer 实例,如 SurfaceViewRenderer 或 TextureViewRenderer。将视频流渲染到 Android 界面上。
  7. EglBase:在渲染视频时,可能需要使用 EglBase 类。EglBase 提供了 OpenGL ES 上下文,用于渲染视频到 Android 视图(如 SurfaceViewRenderer 或 TextureViewRenderer)中。
  8. 音频编解码器:WebRTC 支持多种音频编解码器,如 Opus、G.711、iSAC 等。根据 SDP 信息自动选择合适的编解码器。
  9. 视频编解码器:WebRTC 支持多种视频编解码器,如 VP8、VP9、H.264 等。根据 SDP 信息自动选择合适的编解码器。
  10. 编解码器设置与优化:在特定场景下,可能需要对编解码器的参数进行调整,以获得更好的音视频质量或降低带宽占用。例如,调整视频编码器的分辨率、帧率、码率等参数。
  11. 硬件编解码器支持:在 Android 平台上,可以使用 MediaCodec 进行硬件编解码。并且使用硬件编解码器可以显著降低 CPU 占用,大大提高编解码性能。
  12. ICE(Interactive Connectivity Establishment):处理网络协议,用于在复杂的网络环境中建立 P2P 连接。协助 WebRTC 客户端在 NAT 和防火墙等环境中找到可用的通信路径。
  13. STUN(Session Traversal Utilities for NAT):STUN 服务器帮助 WebRTC 客户端获取公网 IP 地址和端口,以便在 NAT 环境中建立 P2P 连接。STUN 服务器通过向 WebRTC 客户端返回其公网地址,使客户端能够在信令过程中交换这些信息。
  14. TURN(Traversal Using Relays around NAT):当 STUN 服务器无法建立直接的 P2P 连接时,TURN 服务器充当中继,将客户端的数据中转至另一个客户端。虽然这会增加通信延迟,但能确保通信成功。TURN 服务器通常与 STUN 服务器一起部署,作为 WebRTC NAT 穿透的备选方案。

2. 信令流程

WebRTC 不包含信令协议,因此需要开发者根据需求自定义信令过程。

信令主要用于协调双方建立 P2P 连接、交换音视频编码信息、网络地址等。

在 WebRTC 中,信令主要负责以下几个方面:

  1. 协商通信参数:通信双方需要协商一些通信参数,例如音视频编码格式、分辨率等。这些参数被封装在 SDP(会话描述协议)中,并通过信令服务器进行交换。
  2. 发现和交换网络地址:由于 NAT(网络地址转换)的存在,通信双方需要发现并交换其公共网络地址。这一过程通过 ICE(Interactive Connectivity Establishment)协议来实现。

3. SDP(会话描述协议)

SDP 是一种文本格式的协议,用于描述多媒体会话的属性,例如音视频编码格式、分辨率、帧率等。在 WebRTC 中,SDP 主要用于在通信双方之间协商通信参数。

4. NAT 穿透和 STUN/TURN 服务器

在实际网络环境中,大多数用户都位于 NAT(网络地址转换)环境之下。NAT 会导致用户之间无法直接建立 P2P 连接。为了解决这个问题,WebRTC 使用了 ICE 协议,结合 STUN(Session Traversal Utilities for NAT)和 TURN(Traversal Using Relays around NAT)服务器进行 NAT 穿透。

  • STUN:STUN 服务器帮助用户获取公网 IP 地址和端口,供其他用户建立连接。
  • TURN:当 STUN 服务器无法实现 NAT 穿透时,TURN 服务器作为中继,将用户的数据中转至另一个用户。虽然这会增加通信延迟,但能确保通信成功。

ICE 的工作原理如下:

  1. 首先,通信双方收集本地网络地址(包括私有地址和公共地址)以及通过 STUN 和 TURN 服务器获取的候选地址。
  2. 接下来,双方通过信令服务器交换这些候选地址。
  3. 通信双方使用这些候选地址进行连接测试,确定最佳的可用地址。
  4. 一旦找到可用的地址,通信双方就可以开始实时音视频通话。

5.信令服务器

信令服务器负责协调客户端之间的通信,主要包括交换 SDP 信息和 ICE 候选(NAT 穿越信息)。信令服务器可以使用 WebSocket、Socket.IO 等技术来实现。

在选择信令服务器时,开发者需要考虑以下几个方面:

  1. 可靠性:信令服务器需要具有高可靠性,以确保通话过程中的信令消息能够准确无误地传输。
  2. 延迟:信令服务器的延迟应尽可能低,以减少通话建立过程中的等待时间。
  3. 扩展性:随着用户数量的增长,信令服务器需要具有良好的扩展性,以满足更高的并发需求。
  4. 安全性:信令服务器应提供安全机制,例如 SSL/TLS 加密,以防止信令消息被窃听或篡改。

2、WebRTC应用场景

1. 实时音视频通信:

  • 点对点视频聊天:如 Google Meet、Zoom 等实时视频通话应用。
  • 多人视频会议:企业级多人视频会议系统,如飞书、钉钉、腾讯会议、 Cisco Webex、Microsoft Teams 等。
  • 在线教育:远程教育、在线培训和在线课堂等,如腾讯课堂、网易云课堂等。
  • 电子健康:远程医疗咨询、在线心理咨询等。
  • 客户支持:在线客服系统,提供实时音视频客户支持。

2. 实时数据传输和文件共享:

  • P2P 文件共享:直接在浏览器之间传输文件,如 ShareDrop、WebDrop 等。
  • 在线协作工具:实时文档编辑、在线白板等,如 飞书文档、Google Docs、Microsoft Office 365 等。
  • 多人游戏:基于浏览器的实时多人游戏,如 pixelstreaming。
  • 实时数据同步:实时数据同步,如物联网设备状态同步。

3. 实时媒体流处理:

  • 实时视频监控:使用 WebRTC 进行低延迟的实时视频监控。
  • 实时直播:音频和视频直播,如 Facebook Live、Twitch 等。
  • 实时录屏和远程桌面:支持远程桌面访问、协助和实时录屏等功能。
  • 实时音视频处理:实时滤镜、美颜、背景替换等。

4. 物联网(IoT)和边缘计算:

  • 实时设备控制:在浏览器中直接控制物联网设备。
  • 边缘计算:将音视频处理和数据处理任务分布到边缘设备上,减轻服务器负担。
  • 远程团队协作:使用 WebRTC 实现远程工程师对设备的实时控制和诊断。

5. 社交网络:

  • 社交应用:如 QQ、微信、Facebook、WhatsApp 等应用中的实时音视频聊天功能。
  • 直播平台:如 TikTok、抖音、快手 等短视频平台的实时互动直播功能。

由于 WebRTC 可以在不依赖插件或外部应用的情况下实现实时通信,因此在各种需要实时音视频通信和数据传输的场景中都可以发挥重要作用。

3、getUserMedia

getUserMedia 主要就是用来获取设备的媒体流(即 MediaStream)。它可以接受一个约束对象 constraints 作为参数,用来指定需要获取到什么样的媒体流。

navigator.mediaDevices.getUserMedia 是新版的 API,旧版的是 navigator.getUserMedia。为了避免兼容性问题,我们可以稍微处理一下(其实说到底,现在 WebRTC 的支持率还不算高,有需要的可以选择一些适配器,如 adapter.js)。

    // 判断是否有 navigator.mediaDevices,没有赋成空对象
    if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
    }
    
    // 继续判断是否有 navigator.mediaDevices.getUserMedia,没有就采用 navigator.getUserMedia
    if (navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia = function(prams) {
            let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
            // 兼容获取
            if (!getUserMedia) {
                return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }
            return new Promise(function(resolve, reject) {
                getUserMedia.call(navigator, prams, resolve, reject);
            });
        };
    }
    navigator.mediaDevices.getUserMedia(constraints)
        .then(stream => {
            let video = document.querySelector('#Rtc');
            if ('srcObject' in video) { // 判断是否支持 srcObject 属性
                video.srcObject = stream;
            } else {
                video.src = window.URL.createObjectURL(stream);
            }
            video.onloadedmetadata = function(e) {
                video.play();
            };
        })
        .catch((err) => { // 捕获错误
            console.error(err.name + ': ' + err.message);
        });
    navigator.mediaDevices.getUserMedia({ audio: false, video: true });
    // 只需要视频流,不要音频


    // 获取指定宽高,这里需要注意:在改变视频流的宽高时,
    // 如果宽高比和采集到的不一样,会直接截掉某部分
    { 
      audio: false, 
      video: { width: 1280, height: 720 } 
    }

    // 设定理想值、最大值、最小值
    {
      audio: true,
      video: {
        width: { min: 1024, ideal: 1280, max: 1920 },
        height: { min: 776, ideal: 720, max: 1080 }
      }
    }

    // 对于移动设备来说,还可以指定获取前摄像头,或者后置摄像头
    { audio: true, video: { facingMode: "user" } } // 前置
    { audio: true, video: { facingMode: { exact: "environment" } } } // 后置
    // 也可以指定设备 id,
    // 通过 navigator.mediaDevices.enumerateDevices() 可以获取到支持的设备
    { video: { deviceId: myCameraDeviceId } }

    // 设置视频源为屏幕,但是目前只有火狐支持了这个属性
    { audio: true, video: {mediaSource: 'screen'} } 

4、RTCPeerConnection

RTCPeerConnection 接口代表一个由本地计算机到远端的 WebRTC 连接。该接口提供了创建,保持,监控,关闭连接的方法的实现。

RTCPeerConnection 作为创建点对点连接的 API,是我们实现音视频实时通信的关键。在点对点通信的过程中,需要交换一系列信息,通常这一过程叫做 — 信令(signaling)。

在信令阶段需要完成的任务:

 * 为每个连接端创建一个 RTCPeerConnection,并添加本地媒体流。
 * 获取并交换本地和远程描述:SDP 格式的本地媒体元数据。
 * 获取并交换网络信息:潜在的连接端点称为 ICE 候选者。

我们虽然把 WebRTC 称之为点对点的连接,但并不代表在实现过程中不需要服务器的参与。相反,在点对点的信道建立起来之前,二者之间是没有办法通信的。这也就意味着,在信令阶段,我们需要一个通信服务来帮助我们建立起这个连接。WebRTC 本身没有指定某一个信令服务,所以,我们可以但不限于使用 XMPP、XHR、Socket 等来做信令交换所需的服务。

1. NAT 穿越技术

为每个连接端创建一个 RTCPeerConnection,并添加本地媒体流。事实上,如果是一般直播模式,则只需要播放端添加本地流进行输出,其他参与者只需要接受流进行观看即可。

// 因为各浏览器差异,RTCPeerConnection 一样需要加上前缀
let PeerConnection = window.RTCPeerConnection ||
                     window.mozRTCPeerConnection ||
                     window.webkitRTCPeerConnection;
let peer = new PeerConnection(iceServers);


// 参数 — iceServers
// 参数配置了两个 url,分别是 STUN 和 TURN,这便是 WebRTC 实现点对点通信的关键,也是一般 P2P 连接都需要解决的问题:NAT穿越。
{
  iceServers: [
    { 
        url: "stun:stun.l.google.com:19302" // 谷歌的公共服务
    }, 
    {
      url: "turn:***",
      username: ***, // 用户名
      credential: *** // 密码
    }
  ]
}

一般情况下会采用 ICE 协议框架进行 NAT 穿越,ICE 的全称为 Interactive Connectivity Establishment,即交互式连接建立。它使用 STUN 协议以及 TURN 协议来进行穿越。

关于 NAT 穿越的更多信息可以参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/445842.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【npm】node包管理工具npm的介绍和基础使用

简言 npm 是 Node.js 的 包管理器(Package Manager),它是专门用于管理 Node.js 项目中第三方库的工具。 本文介绍下npm和其使用方法。 npm介绍 npm 是世界上最大的软件注册中心。各大洲的开源开发者都使用 npm 共享和借用软件包&#xff…

开源组件安全风险及应对

在软件开发的过程中,为了提升开发效率、软件质量和稳定性,并降低开发成本,使用开源组件是开发人员的不二选择(实际上,所有软件开发技术的演进都是为了能够更短时间、更低成本地构建软件)。这里的开源组件指…

Spring事件发布监听器ApplicationListener原理- 观察者模式

据说监听器模式也是mq实现的原理, 不过mq我还没来得及深入学习, 先用spring来理解一下吧 Spring事件发布监听器ApplicationListener原理- 观察者模式 什么是观察者模式一个Demo深入认识一下观察者模式Spring中的事件发布监听ps 什么是观察者模式 大家都听过一个故事叫做烽火戏…

Git学习笔记(流程图+示例)

概念 图中左侧为工作区,右侧为版本库。Git 的版本库里存了很多东西,其中最重要的就是暂存区。 • 在创建 Git 版本库时,Git 会为我们自动创建一个唯一的 master 分支,以及指向 master 的一个指 针叫 HEAD。(分支和HEAD…

设计模式-结构型模式-代理模式

代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。[DP] // 定义接口 interface Subject {void request(); }// 真实主题对象 class RealSubject implements Subject {Overridepublic void request() {System.out.println(&quo…

redis使用笔记

redis使用笔记 1、Redis简介1.1 含义1.2 功能1.3 特点 2. 常用的数据结构2.1 HASH 3 redis接口定义3.1 redisReply3.2 redisContext3.3 redisCommand 4 实践操作4.1 遇到问题4.1.1 Get哈希的时候返回error4.1.2 长度一直为0,str没法打印(未解决&#xff…

享受当下,2024,一顺百顺!

永远都不要提前焦虑, 也不要一直烦恼, 更不要被当前的情绪耗尽, 那样会对自己的身体造成严重的伤害, 自己只需要好好享受当下就行了。 车到山前必有路,关关难过关关过! 不要执着于过去,也不要过…

10-ARM gicv3/gicv4的总结-基础篇

目录 1、gic的版本2、GICv3/gicv4的模型图3、gic中断号的划分4、GIC连接方式5、gic的状态6、gic框架7、gic Configuring推荐 本文转自 周贺贺,baron,代码改变世界ctw,Arm精选, armv8/armv9,trustzone/tee,s…

LeetCode59:螺旋矩阵Ⅱ

题目描述 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]] 代码 class Solution { public:vector…

AWS 入门实践-远程访问AWS EC2 Linux虚拟机

远程访问AWS EC2 Linux虚拟机是AWS云计算服务中的一个基本且重要的技能。本指南旨在为初学者提供一系列步骤,以便成功地设置并远程访问他们的EC2 Linux实例。包括如何上传下载文件、如何ssh远程登录EC2虚拟机。 一、创建一个AWS EC2 Linux 虚拟机 创建一个Amazon…

GSEA -- 学习记录

文章目录 brief统计学原理部分其他注意事项转录组部分单细胞部分 brief 上一篇学习记录写了ORA,其中ORA方法只关心差异表达基因而不关心其上调、下调的方向,也许同一条通路里既有显著高表达的基因,也有显著低表达的基因,因此最后…

iMazing3 2024详细解析数据备份与恢复备份

iMazing 3的备份功能支持增量备份(类似苹果电脑里的Time Machine功能),意思是第一次把移动设备的数据全部备份下来,之后的备份就只针对数据有变化的那部分,这样可以节省大量的时间和存储空间,不会让使用者为…

LeetCode刷题日志-17.电话号码的字母组合

纯暴力解法&#xff0c;digits有多长&#xff0c;就循环多少次进行字母组合 class Solution {public List<String> letterCombinations(String digits) {List<String> reslut new ArrayList<>();if(digits.equals(""))return reslut;Map<Inte…

ubuntu 23.04 安装 中文输入法

1、安装 fcitx sudo apt install fcitxfcitx 安装好后&#xff0c;可以使用 fcitx-configtool 命令进行配置&#xff0c;其界面如下所示。在这里可以配置不同输入法的切换快捷键&#xff0c;默认输入法等。刚安装系统后&#xff0c;这里只有一个输入法&#xff0c;所以接下来要…

Mysql深入学习 基础篇 Ss.02 详解四类SQL语句

我亲爱的对手&#xff0c;亦敌亦友&#xff0c;但我同样希望你能成功&#xff0c;与我一起&#xff0c;站在人生的山顶上 ——24.3.1 一、DDL 数据定义语言 1.DDL —— 数据库操作 查询 查询所有数据库 show databases; 查询当前数据库 select database(); 创建 create databa…

力扣难题:重排链表

首先通过快慢指针找到中间节点&#xff0c;然后将中间节点之后和之前的部分分为两个链表&#xff0c;然后翻转后面的链表&#xff0c;注意方法&#xff0c;然后将两个链表交替链接。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode…

Unity 使用HyBirdCLR调用Newtonsoft.json报错问题

查了老半天&#xff0c;原来是这里的问题 官方解释 解释&#xff1a; 在Unity的IL2CPP Code Generation中&#xff0c;"Faster runtime"和"Faster (smaller) builds"是两种不同的优化设置选项&#xff0c;它们分别影响着运行时性能和构建大小。下面是它们…

一元函数积分学——刷题(16

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 比较这两种题的求解方法 2.解题思路和步骤&#xff1a; 3.13&#xff1a; 这个题就很适合用万能公式&#xff0c;因为可以把1t2消掉&#xff1a; 也可以用三角…

多模太与交叉注意力应用

要解决的问题 对同一特征点1从不同角度去拍&#xff0c;在我们拿到这些不同视觉的特征后&#xff0c;就可以知道如何从第一个位置到第二个位置&#xff0c;再到第三个位置 对于传统算法 下面很多点检测都是错 loftr当今解决办法 整体流程 具体步骤 卷积提取特征&#xff0c;…

unity学习(53)——选择角色界面--分配服务器返回的信息

好久没写客户端了&#xff0c;一上手还不太适应 1.经过测试&#xff0c;成功登陆后&#xff0c;客户端请求list_request&#xff0c;成功返回&#xff0c;如下图&#xff1a; 可见此时model第三个位置的参数是1.也成功返回了所有已注册角色的信息。 2.之前已知创建的角色信息…