快来,视频会议要开始了

DataFlow范式 DataFlow范式     2022-11-30     737

关键词:

温习下面的几张图片,感受一下今天将带来的主题氛围。  

笔者早在好几年前,做过一段时间的音视频流媒体技术的开发,当然大部分都是自娱自乐,没有实际的生产项目。那么多年过去了,音视频技术成熟度提升很大,而且由于今年的特殊原因,加快了实时音视频应用的爆发。

今天,笔者希望和读者一起重新回顾一下音视频实时互动的流媒体技术。由于音视频流媒体涉及的技术太广,包括但不限于:

  • C/C++ 底层开发

  • 高性能网络服务器

  • TCP/UDP/RTP/RTCP/SRTP/SRTCP/DTLS/STUN/SDP 等协议

  • WebRTC 协议栈

  • 异步 I/O 事件处理

  • 音视频编解码器 H.264/H.265/VP8/VP9 等

  • 媒体协商

  • 信令控制

  • 音视频互动技术的 Mesh/MCU/SFU 架构模型

  • 流媒体服务器 Mediasoup、Janus 等

  • ...

不过,笔者会站在小白用户的角度,从介绍基础内容,再涉及现在流行的 WebRTC,最后通过本地实战部署音视频实时互动项目,实现自家的笔记本、手机、ipad 等实时互动,达到自言自语的目的,让大家体会到成就感。

流媒体

音视频,大家应该都很清楚,通俗来讲就是声音和视频。

引入一个专业术语,流媒体是什么呢?

其实流媒体不是一种新的媒体,而是一种新的媒体传送方式,比如有声音流、视频流、文本流、图像流、动画流等。流媒体和大数据生态中的流数据类似,只是一种传递的方式。

那么流媒体技术又是做什么的呢?举个栗子: 

在多人实时互动的会议中,大家共享音视频,那么你的声音和视频是如何推送给其他所有人的,其他人的音视频又是如何拉取到你的客户端的,网络传输的都是数据,其实这里面就会使用流媒体技术。简单总结就是,流媒体技术是将一连串的媒体数据(声音、视频等)压缩后,以流的方式在网络中分段传送,实现在网络上实时传输音视频以供客户端接收的一种技术。

既然涉及到数据实时传输,那么就需要对数据传输的协议进行规范化。

流媒体传输的网络协议

流媒体协议比较多,笔者挑几个基础的来讲,大家就会明白的。

对于实时音视频流媒体来说,用户期望音视频数据能够及时地从一端传输到另一端,比如网络直播等,其实对于少量的丢包对于用户的观看体验效果影响不明显,但是如果出现较大的延迟和卡顿则严重影响观看体验。由于 TCP 的拥塞控制技术不太适用于这种快速而稳定的流媒体传输,并且重传机制(尤其在极端网络情况下)对于实时流媒体来说既影响效率又没必要,因此,这种情况下一般采用基于 UDP 的方式。

对于 UDP 协议来说,它提供了无连接通信,且不对传送的数据包进行可靠性保证,具有延迟小、数据传输效率高的优点,因此较多地应用于音视频的实时传输。

什么是 RTP

虽然协议这块比较枯燥,但是读者还是需要了解一下,否则总会感觉缺少点东西。但是笔者不会深入讲解协议的头结构、报文细节以及各字段含义,以及通信过程等复杂内容,所以剩下的内容还是值得了解的。

RTP,全名是 Real-time Transport Protocol(实时传输协议)。它是 IETF(国际互联网业界具有一定权威的网络相关技术研究团体,知道很牛就行了)提出的一个标准,对应的 RFC 文档为 RFC3550。RFC3550 不仅定义了 RTP,而且定义了配套的相关协议 RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。

RTP 和 RTCP 各有用途:

  • RTP 用来为语音、视频等实时传输的多媒体数据提供端到端的实时传输服务。RTP 通常使用 UDP 来传送数据,并不保证服务质量,也不保证数据包的顺序可靠传递以及没有流量控制和拥塞控制,这些都依靠 RTCP 来提供服务。

  • RTCP 和 RTP 一起提供流量控制和拥塞控制服务,RTCP 根据实时统计信息,进行流量和拥塞控制。RTP 和 RTCP 配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特适合传送网上的实时数据传输。

我们总结一下 RTP 和 RTCP:

  • 1. RTP/RTCP 为实际的实时流传输协议

  • 2. 整个 RTP 协议由两个密切相关的部分组成:RTP 数据协议和 RTP 控制协议(即RTCP)

RTP 的应用环境

RTP 用在单播或多播网络中传送实时数据,典型的应用场景有简单的多播音频会议、音视频会议和翻译器和混合器等。

为啥又有 RTSP

RTP/RTCP 看起来已经很完善了,为啥又折腾出一个 RTSP 协议呢?

其实可以简单地这样理解:RTP/RTCP 属于偏底层的数据传输的协议(可以回想一下 CM 和 CDH 关系),但是缺少一个应用层的协议。那么笔者还是先讲解完 RTSP,然后大家应该会明白一些的。

RTSP,即实时流协议(Real Time Streaming Protocol),RTSP 通常工作于可靠的传输协议 TCP 之上,用于发起/结束流媒体传输,交换流媒体元信息。从整个体系结构来看,RTSP 位于 RTP 和 RTCP 之上,它可以使用 TCP 或 RTP 完成数据传输。

RTSP 实时流协议,作为一个应用层协议,提供了一个可供扩展的框架,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议(TCP 或 RTP)所提供的某些服务。RTSP 可以对流媒体提供诸如播放、暂停、快进以及检索媒体、添加媒体、邀请加入等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与 RTP 间的交互操作。

前面都是铺垫环节,下面来讲今天的主角 WebRTC。

WebRTC

简史

RTC(Real-time communication),实时通信。音视频实时通信发展很多年了,一直是一项具有挑战性的工作,涉及的技术太多,笔者在文章开头提到的只是一部分,而且上面只是讲解了部分流媒体协议。

回顾历史,由于网络带宽容量,以及业界的一些音视频技术不开源,开发出的产品昂贵,所以存在一段时间发展进度缓慢。

在 2011 年,Google 收购 GIPS 公司(GIPS 公司原是世界顶尖的互联网音视频方案提供商,一家从事音视频实时互动引擎开发的公司,其在音频编解码、网络传输方面具有多年的技术积累和优势),并将其技术重新组织,开源成为现在的 WebRTC。

那么 WebRTC 是什么?我们访问官网(https://webrtc.org),看到一句话,简明扼要:

Real-time communication for the web

借助 WebRTC,可以在基于开放标准的应用程序中添加实时通信功能。它支持在客户端之间发送视频、语音和通用数据,从而使开发人员能够构建功能强大的语音和视频通信解决方案。该技术可在所有现代浏览器以及所有主要平台的本机客户端上使用。WebRTC 背后的技术被实现为一个开放的 Web 标准,并在所有主要浏览器中均以常规 JavaScript API 的形式提供。对于本机客户端(例如Android和iOS应用程序),可以使用提供相同功能的库进行开发。WebRTC 项目是开源的,并得到 Apple,Google,Microsoft 和 Mozilla 等的支持。

总结一下,WebRTC 是一个免费、开放的项目,使 Web 浏览器(例如 Chrome、Firefox、Opera 等)通过简单的 JavaScript API 接口实现实时通信功能。

WebRTC 极大的降低了音视频技术的门槛,一个小的团队都可以基于开源的媒体服务器开发音视频交互应用产品。

可以做什么

WebRTC 提供了许多不同的用例(https://webrtc.github.io/samples/),从使用相机或麦克风的基本 Web 应用程序到更高级的视频通话应用程序和屏幕共享,收集了许多代码示例,以更好地说明该技术的工作原理以及可以使用它的目的。这一块价值非常大,可以参考实现服务端的开发需求。

补充

如今,理解 WebRTC 主要包含两层含义:

  • 由 Google 开源的流媒体客户端,可以进行实时通信,主要应用在浏览器之间实时通信,当然也可以通过使用库来完成移动端、PC 端的通信。

  • WebRTC 定义了一套标准规范,对客户端进行规范定义,比如客户端行为、媒体协商、通信等。

但是对于服务端的服务,比如信令服务端、中继服务和多人实时互动等,WebRTC 并没有定义,需要由使用 WebRTC 厂商自己去定义和实现。

比较流行的方案是基于 WebRTC 和流媒体服务器结合,实现高性能的多方实时互动通信。

当前主流的流媒体服务器有 Licode、Janus、Medooze 和 mediasoup。在本篇文章,读者会介绍 mediasoup 以及对 mediasoup-demo 进行实战操作。

mediasoup

mediasoup 应用于先进的 WebRTC 视频会议。

mediasoup 特点是:

  • 1. 强大的 SFU 开源实现

    由于其通用性、性能和可伸缩性,mediasoup 成为构建多方视频会议和实时流应用程序的理想选择。它具有同步广播、SVC(Scalable Video Coding,可适性视频编码或可分级视频编码,使视频传输更能适应在异质的网络带宽)、传输 BWE(Bandwidth Estimation,WebRTC 和其他 VoIP 系统中用于确定给定会话可用带宽的机制)和许多更先进的功能。

  • 2. Nodejs 模块

    除了创建另一个自用服务器之外,mediasoup 是一个 Nodejs 模块,可以将其集成到更大的应用程序中。mediasoup 提供了一个低层 API,该 API 可以根据用户对应用程序启用不同的用例。

  • 3. 客户端库

    mediasoup 带有 mediasoup-client(JavaScript 库)和 libmediasoupclient(C ++ 库),用于构建使用统一 API 在任何浏览器或设备中运行的应用程序。或只使用 FFmpeg 或 GStreamer 等软件。

SFU

上面提到了 mediasoup 属于强大的 SFU 架构,即 mediasoup 是 SFU 的一种开源实现。这里笔者讲解什么是 SFU 架构。

SFU(Selective Forwarding Unit),选择性转发单元,是一种通过服务器来路由和转发 WebRTC 客户端音视频数据流的方法。

SFU 通信模型如下:  

SFU 服务器最核心的特点是把自己伪装成一个 WebRTC 的 Peer 客户端,WebRTC 的其他客户端其实并不知道自己通过 P2P 连接过去的是一台真实的客户端还是一台服务器。除了伪装成一个 WebRTC 的 Peer 客户端外,SFU 服务器还有一个最重要的能力就是具备一对多通信的能力,即可以将一个 Client 端的数据转发到其他多个 Client 端。

这种网络拓扑结构中,无论多少人同时进行音视频互动,每个 WebRTC 的客户端只需要连接一个 SFU 服务器,上行一路数据即可,极大减少了多人视频通话场景下 Mesh 模型(完全使用 P2P 方式的网络拓扑)给客户端带来的上行带宽压力。

SFU 服务器作为纯粹的数据转发,将数据转发到客户端之后,可以接收到多客户端的数据,对数据进行各种控制或者操作。但是带了一个坏处,如果传输的音视频是采样率大或者高清视频,那么客户端与服务端之间带宽不够的话会导致大量的丢包并影响一些音视频的质量,不过 SFU 也有一系列的配套方案来解决这个问题,如降码率、SVC 分层方式(核心层、拓展层和边缘层)根据带宽来传输不同层的数据。

总结一下,SFU 服务器的优点:

  • 设计具有更好的性能、更高的吞吐量和更少的延迟

  • 具有高度的可扩展性

  • 纯转发,无转码合流,所需资源少,对服务端压力小

  • 灵活性更好,比如可选择性开关任意一路数据的上下行、进行个性化布局(如显示客户端流显示方式)

SFU 在业界比较受欢迎,大部分公司都选择 SFU 方案进行实时音视频架构,常见的开源 SFU 服务器方案有 Licode、Janus,mediasoup 等。

mediasoup 架构

首先看一下 mediasoup 整体架构:

 

mediasoup 流媒体服务器是由 Nodejs 和 Mediasoup(C++) 两部分组成。

  • Nodejs 负责 mediasoup 的信令接收与业务管理,比如创建/消毁房间、创建/关闭生产者以及创建/关闭消费者等。

  • Mediasoup(C++) 这是一个单独的程序,但该程序无法直接启动。因为它在内部会判断是否是 Nodejs 将它启动起来了。只有在 Nodejs 的 mediasoup 管理模块加载之后,再将 Mediasoup(C++) 启动起来,这样它才能正常工作。Nodejs 与 mediasoup 之间通过管道进行通信。

在众多的 WebRTC 流媒体服务器中,mediasoup 可以说是性能最优秀的 WebRTC 流媒体服务器。它使用 C++ 作为开发语言,底层使用 libuv 处理 I/O 事件。

但是,mediasoup 只是提供了一个底层的流媒体库,对于上层的业务逻辑需要我们自己实现,不过内部提供了一个 mediasoup-demo 程序,实现多人的实时音视频互动。

下面笔者带大家进入实战环节。

音视频实时互动实战

环境信息

  1. Mac OS(Ubuntu、基于 Docker 部署等)

  2. Nodejs v10.16.3

  3. npm 6.4.1

  4. gulp 2.2.0

这里只是笔者的环境版本,读者可以随意发挥,只要能跑通即可。

mediasoup-demo 部署

1. 下载源码

$ git clone https://github.com/versatica/mediasoup-demo.git 

$ cd mediasoup-demo 

$ git checkout v3 # 默认为 v3 分支

2. mediasoup-demo 整体分析

  • server

    服务端 Demo,包括如下信息:

    • config.js

      配置文件。

      获取基本的配置信息,提供给 server.js 使用,比如根据服务器核数启动多进程程序,提供服务。

    • server.js

      Demo 主程序。

      首先从 config.js 获取到基本配置信息,启动一些服务,比如 https、websocket 等服务。启动完成后,接收信令数据。当客户端发送信令到服务端时,就会根据不同的信令数据做不同的逻辑处理。

    • connect.js

      对后面 interactiveClient.js 文件的封装。

    • lib

      server.js 要使用的库文件。包括以下几个文件:

      Logger.js:打印日志。

      Room.js:房间管理以及信令处理。

      interactiveClient.js:作为交互的客户端,运行时内部信息查询客户端。

      interactiveServer.js:作为交互的服务端,运行时内部信息查询服务端。

  • mediasoup 作为 C++ 部分

    • lib

      js 文件组成,用于对 mediasoup 的管理工作。

    • worker

      C++ 的核心代码。

  • app 目录

    代表客户端代码。

  • broadcasters 目录

    推流的广播模块。

3. 配置服务端

3.1 npm 安装项目依赖包

$ cd mediasoup-demo/server 

$ npm --registry https://registry.npm.taobao.org install


错误修复(没有错误跳过)
  • 1. npm install 过程中遇到错误:

NPM Error:gyp: No Xcode or CLT version detected!

首先尝试用如下命令进行修复

$ xcode-select --install

系统提示如下信息:

xcode-select: error: command line tools are already installed, use "Software Update" to install updates

而事实上并没有 Software Update 可以更新。如果前面修复不生效,可以使用如下解决方案:

$ sudo rm -rf $(xcode-select -print-path) 

$ xcode-select --install

  • 2. 还有可能会遇到如下问题:

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

报这个错误的原因是 xcode-select 不在默认的路径,解决方法如下:

  • (1) 找到 xcode-select 的当前路径终端命令行

$ xcode-select --print-path /Library/Developer/CommandLineTools

  • (2) 设置 xcode-select 到指定位置

$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer/

  • (3) 验证是否设置成功

$ xcode-select --print-path /Applications/Xcode.app/Contents/Developer

问题都修复成功后,再次执行:

$ npm --registry https://registry.npm.taobao.org install

请耐心等待,包含了 C++ 部分的编译。

3.2 配置文件

$ cd mediasoup-demo/server 

$ cp config.example.js config.js

修改 config.js 中的 IP 地址:

config.js 中需要提供 TLS 证书和密钥,我们可以在本地生成:

$ req -x509 -nodes -days 365 -newkey rsa:2048 -subj /CN=Rui -keyout server.key -out server.crt

再次修改 config.js,

配置证书和密钥:

如果部署到服务器上提供公网访问,需要购买域名和证书。

4. 启动服务端

$ cd mediasoup-demo/server 

// 如果没有 forever,请使用 npm 安装 

$ forever start server.js

5. 启动客户端

$ cd mediasoup-demo/app 

$ npm install 

$ npm install -g gulp-cli

如果安装比较慢,使用国内镜像仓库,比如 https://registry.npm.taobao.org。

启动客户端:

6. 多用户音视频互动体验

gulp live 执行后,会弹出浏览器。请求访问麦克风和摄像头:  

授权后,正常进入房间: 

为了本地测试,我们把拷贝该地址(https://192.168.31.52:3000/?info=true&roomId=ezyqzldt),再打开两个窗口,就会出现该房间中有三个用户,如下: 

当然在家中局域网内,可以使用手机和平板电脑等同时访问,进行自问自答,或者和小朋友互动。mediasoup-demo 也可以共享屏幕、开启和禁止音视频和文字聊天等功能,大家尽情的实战吧。

通过 Nodejs 实现 Web 服务(补充)

上面我们将 mediasoup-demo 运行在本地,但是如果想让多个人真正使用 mediasoup-demo 时,必须要部署到服务端。

mediasoup 包括三部分:

  1. WWW 服务

  2. 信令处理服务

  3. C++ 媒体流处理服务

如果 WWW 服务部署在服务器,没有可视化终端和浏览器,WWW 服务就不能通过 gulp live 命令行方式启动了,而是需要放到 Web 服务上,浏览器直接访问 Web 服务,将客户端代码下载下来,然后再连接信令服务器,最终进行音视频流的互通。

通过 Nodejs 实现 WWW 服务还是比较简单的,感兴趣的读者,可以参考官网实现,如果遇到困难,可以留言交流。

总结

我们来看一下现如今流媒体服务器的应用场景:

  • 在线教育

  • 音视频会议

  • 直播连麦

  • 即时通信

  • 多终端融合

  • 多协议融合

  • 多人互动游戏

  • 远程医疗

5G 时代,必将会加快推进实时互动音视频技术的发展和多元化应用。

参考

  • https://webrtc.org

  • https://mediasoup.org

  • https://github.com/versatica/mediasoup-demo

  • https://www.jianshu.com/p/651e5cf181fd

计划会议要开始了,产品负责人却没来…

...c;Sprint计划会议(简称计划会议)作为一个Sprint的开始,产品负责人(简称PO)要和开发团队一起确立本次Sprint的目标,否则开发团队可能就不知道做什么,进而无法开展Sprint中的活动。本文分享自华为... 查看详情

技术移民直通车要发车了-快来秒杀你的车票

你是否觉得新西兰技术移民离你甚远?你是否觉得技术移民是一件非常艰难的事情?你是否希望挣脱人生瓶颈换一个自然环境生活,但却苦于没有门路?或者你已经在移民的道路上,但遥遥无期的等待让你不知何去何从? 也许... 查看详情

快来解锁小程序蓝牙开发技能(代码片段)

微信小程序中很早就支持了蓝牙能力,看过不少的文档,知道大概的流程和能实现的效果,但是由于一直没有像样的实战项目导致也没有正经的开发上线过,本次缘于接到了一个外包项目,那就顺道记录一下开发的过程及遇到的... 查看详情

❤️快来领取国庆节专属头像!!26种样式随你挑!❤️(代码片段)

最近大家是不是看到很多朋友的头像已经换成国庆专属头像了?我去小程序看了一下,发现要看视频或者广告才能保存图片,真的太气人了!!于是想自己写一个网页版,随心所欲选择样式,想换就换&... 查看详情

格式工厂是怎么合并mp4视频的?

...级→视频合并→点击要合并的视频→添加→确定→确定→开始,OK。合并不成功方法下载地址查看你的百度消息。这里不让添加链接。参考技术A格式工厂合并视频方法步骤如下:1、在电脑中下载安装格式化工厂软件,然后打开... 查看详情

首届微软研究峰会视频上线,快来查收你的独家观看指南!

由微软全球八大研究院携手倾力打造的首届微软研究峰会MicrosoftResearchSummit2021已于此前在线上成功举办。来自世界各地的300余位顶尖科学家和技术领导者为大家带来了150场精彩分享,内容围绕“科学、赋能、可持续发展、医... 查看详情

快来给你的宠物视频加个表情特效吧

摘要:我们将给猫贴一张卡通脸,给ElonMusk贴上小胡子,给小狗贴上驯鹿角!本文分享自华为云社区《​​视频AI,给你的宠物加个表情特效!​​》,作者:HWCloudAI。GAN监督学习是一种联合端到端学习判别模型及其GAN生成的训... 查看详情

androidoapi已发布最终版本,快来尝尝鲜(代码片段)

在三周前举行的GoogleI/O大会上,我们宣布了AndroidO的第二个开发者预览版,同时介绍了FluidExperiences和Vitals等重要主题,并且重点介绍了我们利用Treble项目实现库模块化方面的工作进展。此次大会上还发布了首个测试版... 查看详情

第一阶段站立会议06

一、站立会议信息  前端的设计基本上已经完成了,要开始进行后端的处理,包括数据库的操作和表单的提交,分页的处理,查询的展示,功能复杂,一起进行了研讨。二、任务进度  设计完成了注册登录功能,对消息的表... 查看详情

如何在 iPad 中从之前停止的位置开始播放视频?

】如何在iPad中从之前停止的位置开始播放视频?【英文标题】:HowtostartthevideoiniPadfromwhereitwasstoppedearlier?【发布时间】:2013-01-2806:54:27【问题描述】:我正在iPad上播放视频,然后使用iPad上的“主页”按钮停止播放。当我再次开... 查看详情

快来跟我一起学react(day7)(代码片段)

简介我们继续上一节的内容,开始分析React官网:https://reactjs.org/docs/accessibility.html的“高级指引”部分,这一部分会涉及到Refs转发、Fragments、高阶组件等概念的分析,比前面章节的难度还是略微大一些的,所... 查看详情

快来跟我一起学react(day1)(代码片段)

简介因为目前公司的技术栈都是Vue,之前有在React-Native的项目中接触过React,但并没有深入的去了解过,从现在开始,我就把自己当成一个React小白了,决定挑战一下自己,从0开始入手React,中间会不断... 查看详情

快来跟我一起学react(day6)(代码片段)

简介我们继续上一节的内容,开始分析React官网:https://reactjs.org/docs/accessibility.html的“高级指引”部分,这一部分会涉及到异步组件、全局上下文对象、错误边界组件等概念的分析,比前面章节的难度还是略微大... 查看详情

java老师又要提问了,不会又要扣期末成绩,大神快来指点一下呀!不用解释太深,急求答案!!

1、答:如果成员变量是私有的那么,在类外肯定是不能直接访问这些私有变量的,如果想访问的话,那么就必须使用get、set访问器,例如:classAintnum;publicintgetNum()returnnum;publicvoidsetNum(intnum)this.num=num;classBpublicvoidtest()Aa=newA();intnum=a.... 查看详情

视频号小店开始收技术服务费是多少

视频号最近有一个比较大的政策,从下个月1号开始,视频号小店要收技术服务费了,是昨天下午的一个消息,这里面也有一个针对于新商家的优惠费率政策,也就是新开店的商家在30天之内,如果销售额没... 查看详情

proxmoxve继续稳定运行,快来围观

超融合集群无故障运行超过500天,从历史数据看,CPU资源绰绰有余,内存耗费较多,以后分配得精打细算。ceph分布式去中心化存储,每个osd(单盘)耗费大约5g的内存,如果一个物理服务器插8个单盘做osd的话,40g的内存就没了... 查看详情

剪辑教程如何给视频添加配音旁白,三种文字转语音方法教给你

...剪辑完成,应该如何给视频配音?三种配音方法快来学现在许多自媒体都居家创作短视频,那么给短视频配音的问题就摆着了面前,怎么给我们的短视频配音呢,接下来就教大家三种给视频添加配音的方法。... 查看详情

原生js实现飞机大战游戏超详细解析快来做一个自己玩吧(代码片段)

...实现FlappyBird游戏:原生JS实现FlappyBird游戏超详细解析快来做一个自己玩吧原生JS实现本地存储记账本:我用JS做了一个记账本[数据可本地存储]附万字详解1.案例分析💨我们先思考一下这个游戏都由哪几个部分或者说... 查看详情