WebRTC 媒体服务器

作者:追风剑情 发布于:2024-1-15 12:53 分类:Unity3d

  开源社区里可用的 WebRTC 媒体服务器有 Licode、OWT、Kurento、Jitsi、Janus、Medooze 和 Mediasoup。其中,能够作为 MCU 使用的有 Licode、OWT、Kurento、Medooze,能够作为 SFU 使用的有 Licode、OWT、Kurento、Jitsi、Janus、Mediasoup。

下面我们对其中几个具有代表性的媒体服务器进行介绍。

OWT

  OWT(Open WebRTC Toolkit) 是 Intel 在 2014 年推出的针对 WebRTC 的开发套件。该套件包含了优化 Intel 硬件的服务器和客户端 SDK。Intel 持续为该套件增加新的特性,并于 2018 年将该套件开源。

  OWT 既可以充当多点控制单元(MCU),又可以作为选择性转发单元(SFU) 使用。它还提供了对媒体进行解码、处理和重新编码后再将其发送回客户端的能力。

OWT 包含的主要功能如下。

  • 多方视频会议。尽管大多数 WebRTC 应用程序使用 SFU 作为主要的网络架构,但是在客户端能力受限的情况 (如IoT 设备)下,仍然需要使用 MCU 模式。OWT 支持这两种模式。
  • 转码。OWT 支持对音视频进行转码,以适应不同的应用场景。
  • 将 WebRTC 转成其他视频格式。OWT 支持将 WebRTC 的 RTP 流转换为 RTSP、RTMP、HLS 等格式,以便非 WebRTC 接入的客户端也能观看实时流。
  • 录制。OWT 支持将音频及视频存储到磁盘。
  • SIP 网关。OWT 可以作为 SIP 网关使用。
  • 视频分析。OWT 支持使用机器学习对视频内容进行分析。

OWT 应用层使用 Node.js 开发,媒体处理层使用了 C++ 语言,数据库使用 MongoDB,消息通信使用了 RabbitMQ。

OWT 还提供了全平台的客户端 SDK,可以方便地整合到业务之中。

Kurento

  Kurento 开源项目包含了一个 WebRTC 媒体服务器(KMS) 和一组与之通信的客户端 API。使用 Kurento 可以简化 Web 及移动端音视频应用程序的开发过程。Kurento 提供的功能包括音视频实时通信、实时转码、服务器端录制、合流、广播等。

Kurento 的特性有以下几个。

1.动态 WebRTC 媒体管道
  Kurento 允许使用自定义媒体管道连接到 WebRTC 对等设备,例如 Web 浏览器和移动应用程序。这些媒体管道包括播放器、记录器、混音器等,即使在媒体已经连通的情况下,也可以在任何时间点对这些媒体管道进行组合、激活或停用。

2.客户端/服务器架构
  使用 Kurento 开发的应用程序遵循客户端/服务器架构。Kurento 媒体服务器(KMS)提供了支持 Kurento 协议的 WebSocket 接口,该接口允许客户端应用程序定义管道拓扑。

3.Java和JavaScript客户端应用程序
  KMS 部署的典型示例包括 3 层体系结构,其中用户的浏览器通过中间客户端应用程序与 KMS 服务器交互。有几个官方的 Kurento 客户端库,支持在客户端应用程序中使用 Java 和 JavaScript。遵循 WebSocket 协议,可以轻松开发自己的客户端 SDK。

4.第三方模块
  Kurento 媒体服务器具有基于插件的可扩展结构,该结构允许第三方自定义模块。通过自定义模块,可以将任何媒体处理算法集成到 WebRTC 应用程序中,例如集成计算机视觉增强现实、视频索引和语音分析等。

Kurento Media Server 的代码是开源的,根据Apache License Version 2.0 的条款发布可在 GitHub 上免费获得。

Janus

  采用C语言实现的 Janus 是一个 Liux 风格编写的 WebRTC 媒体服务器开源项目,支持在 Linux/MacOS下编译、部署,但不支持 Windows 环境。

  Janus 分为两层: 插件层和传输层。Janus 插件的设计类似于 Nginx,用户可以根据自己的需要动态加载或卸载插件,也可以根据自身业务需要编写自己的插件。Janus 默认支持的插件如下。

  • SIP: 该插件提供了对 SIP 协议的支持,使得 WebRTC 协议与 SIP 协议可以相互通信。
  • TextRoom: 该插件使用 DataChannel 实现了一个文字聊天室应用。
  • Streaming: 允许 WebRTC 终端观看/收听由其他工具预先录制生成的文件或媒体。
  • VideoRoom: 实际上就是一个音视频路由器,实现了视频会议的 SFU 服务。
  • VideoCall: 这是一个简单的视频呼叫应用,允许两个 WebRTC 终端相互通信,它与 WebRTC 官网的例子( WebRTC 官网的例子https://apprtc.appspot.com )相似,不同之处在于这个插件要经过服务器端进行音视频流中转,而是 P2P 直连。
  • RecordPlay: 该插件有两个功能,一个是将发送给 WebRTC 的数据录制下来,另一 个是通过 WebRTC 进行回放。

媒体数据传输层主要实现了 WebRTC 中的流媒体及其相关协议,如 DTLS、ICE、SDP、RTP、SRTP、SCTP 等。

  信令传输层用于处理Janus 的各种信令,支持的信令传输协议包括HTTP/HTTPS、WebSocket/WebSockets、NanoMsg、MQTT、PfUnix 和 RabbitMQ。不过需要注意的是,有些协议是可以通过编译选项控制是否安装的,也就是说这些协议并不是默认全部安装的。另外,Janus的所有信令都采用JSON格式。

  Janus 整体架构采用了插件的方案,这种架构方案非常优秀,用户可以根据自己的需要,非常方便地在上面编写应用程序。Janus 支持的功能非常多,比如 SIP、RTSP、音视频文件的播放和录制等,所以在融合性上比其他系统有非常大的优势。另外,Janus 的底层代码是由C语言编写的,性能非常强大。Janus 的开发、部署手册非常完善,因此它是一个非常优秀的开源项目。

Mediasoup

  Mediasoup 是一个较新的 WebRTC 媒体服务器,其底层采用C++实现,外层使用Node.js 进行封装。Mediasoup 服务器端以 Node.js 模块的形式提供。

Mediasoup 及其客户端库的设计目标如下。

  • 成为一个 WebRTC SFU。
  • 支持 WebRTC 协议,并支持输入、输出普通的 RTP 流。
  • 在服务器端提供一个 Node.js 模块。
  • 在客户端提供小型 JavaScript 和 C++ 库。
  • 极简主义: 只需处理媒体层。
  • 与信令无关: 不强制使用任何信令协议。
  • 仅提供底层 API。
  • 支持所有现有的 WebRTC 协议。
  • 支持与其他开源多媒体库/工具进行集成。

  Mediasoup 支持 Simulcast 和 SVC,底层使用 C++ 开发,使用 libuv 作为异步IO事件处理库,保证了数据传输的高效性。Mediasoup 的实现逻辑非常清晰,它不关心上层应用如 何做,只关心底层数据的传输,并将其做到极致。

  与 Janus 相比,Mediasoup 更关注数据传输的实时性、高效性和简洁性,而 Janus 相对来讲更加复杂一些。

Mediasoup 作为 SFU 媒体服务器的优点如下。

  • 相比于其他媒体服务器,Mediasoup 的编译、安装操作最为简单,无须处理复杂的依赖包问题,使用npm 工具就可以直接安装。
  • Mediasoup 结构清晰、合理,代码书写规范,易于理解、掌握。
  • Mediasoup 开发较为活跃,不断有新的特性加人,支持最新的 WebRTC规范。
  • Mediasoup 性能好,在多核 CPU 系统上,每核运行一个 Worker 实例,每个 Worker 可以支撑 500 个消费者。
  • Mediasoup 服务器端和客户端都支持使用 TypeScript,易于全栈开发。

  与其他的 SFU 相比,Mediasoup 最大的不同是它不能作为一个独立的服务器使用,而是以 Node.js 模块的形式存在,这样做的好处是可以整合到更大的应用程序中,不受自身的限制。在服务器端引人 Mediasoup 的方式如下。

const mediasoup = require("mediasoup");  

  在 Node.js 模块内部,Mediasoup 可以分为两个独立的组件: 一个 JavaScript 层,提供了适用于 Node.js 的现代 ECMAScriptAPI; 一组处理媒体层(ICE、DTLS、RTP等)的C/C++子进程(Worker)。

  这两个组件通过进程相互通信,但是,从开发人员的角度来看,应用程序只需要关注 JavaScript API 层。

  Mediasoup 把每个实例称为一个子进程,通常在每核 CPU 上启动一个子进程。在子进程内部有多个 Router,每个 Router 相当于一个房间。在每个房间里可以有多个参与者,每个参与者在 Mediasoup 中由一个 Transport 代理。换句话说,对于 Router,一个 Transport 就相当于一个用户。

  Mediasoup 分为3类 Transport,即 WebRtcTransport、PlainRtpTransport 和 PipeTransport。

  WebRtcTransport 用于与 WebRTC 类型的客户端进行连接,如浏览器、WebRTC移动端等。

  PlainRtpTransport 用于与传统的 RTP 类型的客户端连接,通过该 Transport 可以播放多 媒体文件、执行媒体录制等。

  PipeTransport 用于实现 Router 之间的连接,也就是一个房间中的音视频流通过 PipeTransport传到另一个房间。由于一个 Router 只能运行在单核上,因此借助 PipeTransport 可以充分利用多核 CPU 的特性,支持更多人同时在线。

  每个 Transport 可以包含多个 Producer 和 Consumer。Producer 表示媒体流的生产者,分为两种类型,即音频生产者和视频生产者。Consumer 表示媒体流的消费者,也分为两种类型,即音频消费者和视频消费者。

Mediasoup 信令交互过程

  Mediasoup 的信令交互本质上与原生 WebRTC 的信令交互是一样的。Mediasoup 在其提供的客户端及服务器端库中封装了 WebRTC 的原生 API,如 createOffer()、createAnswer()等方法都封装在 Transport 的 API 中。

Mediasoup信令交互过程.png

通常由客户端发起信令交互,流程如下。

  • 客户端通过信令服务器获取服务器端的 RTP 能力。
  • 客户端调用 mediasoup.Device.load0 方法传人服务器端的 RTP 能力。
  • 客户端通过信令服务器向服务器端发送创建 WebRTC 传输通道的指令,服务器端调用 router.createWebRtcTransport() 方法创建传输通道,返回服务器端的传输通道信息 TransportInfo。

如果客户端创建的是发送通道,则进一步的流程如下。

  • 客户端使用 TransportInfo 作为参数,调用 mediasoup.Device.createSendTransport()方法创建客户端的发送 Transport。
  • 客户端在刚刚创建的 Transport 上监听 connect 事件,当该事件被触发时,通过信令服务器向服务器发送连接 WebRTC 传输通道的指令,服务器端随后调用 transportconnect() 方法建立连接。
  • 客户端在刚刚创建的 Transport 上监听 produce 事件,当该事件触发时,通过信令服务器向服务器端发送创建生产者的指令,服务器端调用 transport.produce()方法创建服务器端的生产者。当客户端调用 Transport.produce() 方法发布媒体流时,才会触发 produce 事件。
  • 当服务器端收到创建生产者的指令时,还会发送 newConsumer 事件通知房间中其他的参与者,其他参与者则在接收通道接收新发布的媒体流。

如果客户端创建的是接收通道,则流程如下。

  • 客户端使用 TransportInfo 作为参数,调用 mediasoup.Device.createRecvTransport() 方法创建客户端的接收 Transport。
  • 客户端在刚刚创建的 Transport 上监听 connect 事件,当该事件触发时,通过信令服务器向服务器端发送连接 WebRTC传输通道的指令,服务器端随后调用 transportconnect()方法建立连接。
  • 如果客户端收到了newConsumer 事件,则调用 Transport.consume() 方法接收新发布的媒体流,通过 consume.track 获取媒体轨道。

媒体服务器的选择

  开源社区的几个媒体服务器各有特色,在实际应用中应根据项目需要进行选择。当需要采用MCU方案时,推荐使用OWT;当需要在服务器端对媒体流进行处理,比如增加人脸识别等功能时,推荐使用 Kurento; 当构建通用的WebRTC平台时,Janus 基于插件的模式更为合适; 如果希望打造单一的视频通话应用,则推荐使用 Mediasoup。

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号