欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mediasoup中文文档(本人尝试翻译,后续陆续更新)

程序员文章站 2022-07-14 20:44:46
...

使用说明

  1. ???代表有疑问,需要后续补充

  2. 官网地址:官网文档目录链接

mediasoup 官方文档代码走读、翻译

总览

一个SFU(选择性转发单元)从终端接收音频和视频流然后转发给其他终端。每个接收终端可以选择接收的流和时空层。与mixer或MCU(多点控制单元)相比,该设计具有更好的性能,更高的吞吐量和更少的延迟。它具有高度的可扩展性,并且由于不需要转码或混合媒体,因此所需资源少得多。

由于端点分别获取其他端点的媒体,因此它们可以具有个性化的布局,并选择要呈现的流以及如何显示它们。

软件设计宗旨

  • 是一个选择转发单元;(并列的还有一个MCU-多点控制单元,几年前比较流行;Mesh -网状模型,即多个终端之间两两进行连接,形成一个网状结构;不同码流模型的本质差异)
  • 支持WebRTC和普通RTP输入和输出
  • 在服务器端设计的是Node.js模块
  • 客户端是小型JavaScript和C ++库
  • 是极简主义设计:只处理媒体分层(分层概念,参考RTP-SVC标准)
  • 与信令无关: 不强制任何信令协议
  • 非常低级别的API(mediasoup和它的客户端库提供一个超级低级的API。它们的目的是使不同的用例和场景,没有任何约束或假设。)
  • 支持现存所有类型的webRTC终端;(webRTC终端 是基于webRTC实现的终端)
  • 使与众所周知的多媒体库/工具 可以集成

用例

mediasoup及其客户端库提供了超低级的API。它们旨在实现各种用例和场景,而没有任何约束或假设。其中一些用例是:

  • 组视频聊天应用程序。
  • 实时一对多(或很少对多)广播应用程序。
  • RTP流。

V3 与V2的差异

简而言之,mediasoup v3和mediasoup-client v3(除了新的libmediasoup C ++库)都比其相应的v2版本低级别(参考软件宗旨-low level API)得多,并且具有大量的改进和新功能。下表仅列出最具吸引力的部分:

Feature v2 v3 Description
mediasoup protocol 【协议】 [√] [] v2 comes with a set of JSON messages that must be blindly exchanged between client and server. While this makes the client side “theoretically easier” it difficults the server side logic. In v3, instead, mediasoup provides a comprehensive low level JavaScript API in both client and server sides, so the application knows which exact kind of information it exchanges between client and server.
【v2带有一组JSON消息,必须在客户端和服务器之间盲目交换。尽管这使客户端“从理论上讲更容易”,但使服务器端逻辑变得困难。
相反,在v3中,mediasoup在客户端和服务器端都提供了全面的底层JavaScript API,因此应用程序知道在客户端和服务器之间交换的确切信息种类。】
Peers [√] [] v2 includes the concept of “peers” in its API. A peer is just a container that holds transports, producers and consumers (in fact, a peer just exists in the mediasoup JavaScript land). v3 gets rid of “peers” and enforces a low level API based on transports that hold producers and consumers. It’s up to the application to handle “peers” at signaling level (if needed) and associate mediasoup entities with those “peers”.
【v2在其API中包含“对等”的概念。对等点只是一个容器,用于保存传输、生产者和消费者(实际上,对等点仅存在于mediasoup JavaScript领域中)。
v3摆脱了“对等”,并基于容纳生产者和消费者的传输强制执行低级API。由应用程序来处理信令级别的“对等”(如果需要),并将mediasoup实体与那些“对等”相关联】
Routers [] [√] In v2 a mediasoup room holds peers. In v3, room has been renamed to router and does not hold peers but transports. Renaming it to router makes it fit much better to what it really does.
【在v2中,mediasoup会议室可容纳对等方。在v3中,会议室已重命名为路由器,并且不容纳对等端,但可以进行传输。将其重命名为路由器使其更适合其实际功能。】
Plain RTP injection [] [√] v3 provides a unified API to inject or extract audio/video into/from a mediasoup router using plain RTP or WebRTC transports. This makes it easy to integrate well known softwares such as FFmpeg or GStreamer into a mediasoup based application.
【v3提供了一个统一的API,可以使用普通的RTP或WebRTC传输,向mediasoup路由器中注入音频/视频或从中提取音频/视频。这使得将诸如FFmpeg或GStreamer之类的知名软件轻松集成到基于mediasoup的应用程序中变得容易。】
Multiple binding IPs [] [√] In mediasoup v2 just a static IPv4 and IPv6 pair can be assigned to all transports. In v3, instead, each transport can be provided with multiple and different IPv4 and/or IPv6 addresses. This enables scenarios in which media is conveyed through public and private network interfaces.
【在mediasoup v2中,只能将静态IPv4和IPv6对分配给所有传输。相反,在v3中,可以为每个传输提供多个不同的IPv4和/或IPv6地址。这将启用通过公共和专用网络接口传输媒体的方案。】
Per worker settings [] [√] mediasoup v2 exposes a Server class that internally handles N workers (media subprocesses) sharing them all the same settings. In v3 the application creates each worker independently and can assign different settings to them (such as ports range, log level and so on).
【mediasoup v2公开了一个Server类,内部处理N个工作程序(媒体子进程)的类,这些工作程序将它们共享所有相同的设置。在v3中,应用程序独立创建每个工作程序,并可以为其分配不同的设置(例如端口范围,日志级别等)。】
Horizontal scalability [] [√] By using the new pipe transports in v3, two mediasoup routers running in the same or different hosts can be interconnected at media level, increasing the broadcasting capabilities by enabling usage of multiple CPU cores even in different machines. More info about this here.
【通过在v3中使用新的管道传输,可以在媒体级别将在相同或不同主机上运行的两个mediasoup路由器互连,甚至在不同的机器中也可以使用多个CPU内核来提高广播功能变得可行。】
Sender side BWE [] [√] mediasoup v3 implements sender side bandwidth estimation to automatically switch between spatial/temporal layers in consumers thus accommodating the total transport bitrate to the bandwidth available in the receiver endpoint.
【mediasoup v3实现了发送方带宽估算,可以在用户的时间/空间层之间自动切换,从而将总传输比特率调整为接收方端点中可用的带宽。】
Unlimited video layers [] [√] mediasoup v2 limits the number of simulcast video streams to 3 (“low”, “medium” and “high”). mediasoup v3 can handle unlimited spatial and temporal layers and refers to them by their numeric index (from 0 to N).
【mediasoup v2将联播视频流的数量限制为3(“低”,“中”和“高”)。mediasoup v3可以处理无限的空间和时间层,并通过其数字索引(从0到N)引用它们】
Stream score [] [√] mediasoup v3 notifies the application with scores for every RTP stream (in producers and consumers), allowing the application to know how the overall transmission quality is in every sender and receiver.
【mediasoup v3通过每个RTP流(在生产者和消费者中)的分数来通知应用程序,使应用程序知道每个发送者和接收者的总体传输质量。】

客户端与服务器之间的通信

Check the RTP Parameters and Capabilities section for more details.

mediasoup不提供任何信令协议来与客户端和服务器进行通信。应用程序可以使用WebSocket,HTTP或任何一种通信方式来进行通信,并在客户端和服务器之间交换与mediasoup相关的参数,请求/响应和通知。在大多数情况下,此通信必须是双向的,因此通常需要全双工信道。但是,应用程序可以将同一通道重新用于与非媒体汤相关的消息交换(例如身份验证过程,聊天消息,文件传输以及应用程序希望实现的任何功能)。

mediasoup-client和libmediasoupclient的准则

假设我们的JavaScript或C ++客户端应用程序实例化mediasoup-client Device或libmediasoupclient Device对象以连接到mediasoup router(已在服务器中创建)并通过WebRTC发送和接收媒体。

mediasoup-client(客户端JavaScript库)和libmediasoupclient(基于libwebrtc的C ++库)均生成适用于mediasoup的RTP参数,从而简化了客户端应用程序的开发。

信令和 Peers

应用程序可以使用WebSocket,并将每个经过身份验证的WebSocket连接与“peer”关联。

请注意,mediasoup中本身没有“peers”。但是,应用程序可能希望定义“peers”,“peers”可以标识并关联特定的用户帐户,WebSocket连接,元数据以及一组Mediasoup传输,生产者,消费者。数据生产者和数据消费者。

设备加载

device.load()

通过向客户端应用程序提供服务器端mediasoup路由器的RTP能力,客户端来加载其mediasoup设备。

device.load({ routerRtpCapabilities })

使用mediasoup路由器的RTP功能加载设备。这是设备了解允许的媒体编解码器和其他设置的方式。

创建 “Transports”

mediasoup-client和libmediasoupclient都需要单独的WebRTC-“transports"进行发送和接收。通常,客户端应用程序甚至在希望发送或接收媒体之前都会预先创建那些"transports”。

For sending media: 发送媒体

接收媒体

如果在这些传输上需要SCTP(WebRTC数据通道),则enableSctp必须在服务器端WebRTC传输(具有正确的numSctpStreams)和其他与SCTP相关的设置中启用。

生产媒体

一旦创建发送"transport "后,客户端应用程序可以在其上产生多个音频和视频轨道。

  • 该应用程序获取 track(例如,通过使用navigator.mediaDevices.getUserMedia()API)
  • 它在本地发送传输中调用 transport.produce()
    • 如果这是第一个调用transport.produce(),则"transport "将发出“ connect” 动作
    • "transport "将发出 “produce” ,因此应用程序会将事件参数传输到服务器,并在服务器端创建一个Producer实例
  • 最后,transport.produce()将在客户端使用Producer实例进行解析

消费媒体

创建接收transport 后,客户端应用程序可以在其上使用多个音频和视频轨道。但是顺序相反(这里必须先在服务器中创建消费者consumer)。

  • 客户端应用程序将其device.rtpCapabilities信号发送给服务器(它可能已经提前完成)。
  • 服务器应用程序应检查远程设备是否可以使用特定的生产者producer(即,它是否支持生产者的媒体编解码器)。它可以通过使用router.canConsume()方法来实现。
  • 然后,服务器应用程序调用客户端为接受媒体所创建的WebRTC transport中的 transport.consume(),从而生成服务器端的消费者consumer。
    • transport.consume()文档中所述,强烈建议使用暂停paused创建服务器端消费者consumer,并在远端中创建consumer后将其恢复(当创建一个消费者推荐设置暂停参数为true,那么消费者的参数传递到消费终端,一旦消费终端创建其本地消费者,使用resume()方法来恢复服务器端消费者)。
  • 服务器应用程序将消费者consumer信息和参数传输到远程客户端应用程序,该客户端应用程序在本地接收传输中调用transport.consume()
    • 如果这是第一个调用,则transport将发出“ connect” transport.consume()
  • 最后,transport.consume()将在客户端使用Consumer实例进行解析。

可扩展性

‘可扩展性’ 是一个模糊的概念,可以应用于不同的场景和需求。下面揭露了其中一些场景。

在进入细节之前,让我们澄清一下mediasoup内部的工作方式:

  1. ‘mediasoup’是一个Node.js库,它公开了一个JavaScript API以管理’workers’,‘routers’,‘transports’,'producers '和 ‘consumer’(以及其他)。
  2. 一个 'worker’代表一个’mediasoup ‘C ++子进程,运行在单个CPU核心上,它可以处理许多’routers’
  3. 一个’router’容纳在’producers ’ 和 'consumers’之间,在他们之间交换音频/视频RTP码流。在某些常见用法中,一个’router’可以理解为一个“多方会议室”。
  4. 由于一个’router’属于一个’worker’,因此’router’使用单个CPU(并且可以与同一工作服务器中的其他路由器共享该CPU)。
  5. 一个’router’相当于一个SFU(选择性转发单元)。这是由于:
    1. 它在’producers ’ 和 'consumers’之间转发RTP数据包
    2. 它根据用户设置和网络功能选择要转发的空间和时间层
    3. 当数据包丢失时,它向生产者端点请求’RTP数据包重传’
    4. 它拥有一个缓冲区,其中包含来自’producer’-‘endpoint’的数据包,并在这些端点请求时将其重新传输给’consumer’-‘endpoint’
    5. 但是,它既不解码也不对媒体数据包进行转码,因此它不能按需生成视频关键帧,而只是将其请求给’producer’-‘endpoint’。

mediasoup中文文档(本人尝试翻译,后续陆续更新)

多个独立的’mediasoup '-‘routers’

这种情况的一个很好的例子是提供多方会议室的应用程序。每个会议室都使用一个单一的’mediasoup’-‘router’,因此每个’mediasoup’-‘worker’(使用单个CPU)可以容纳多个“会议室”。

根据主机CPU的能力,‘mediasoup ‘C ++子进程总共可以处理约500个’consumers’。例如,如果一个房间中有4个’peers’(可以理解为终端,v2中的概念,v3没有了),他们都发送音频和视频,而他们都消费了其他对等方的音频和视频,则这意味着:

  • 每个’peer’都从3个’peers’接收音频和视频,因此3x2 = 6个’consumers’。
  • 有4个’peers’,因此4x6 = 24个’consumers’。

根据所需的功能,使用mediasoup的服务器端应用程序应根据需要启动任意数量的’workers’(不超过主机中CPU内核的数量),并在它们之间分配“rooms” (mediasoup-routers)。

如果需要更高的能力,则应用程序后端应在多个主机中运行mediasoup,并在它们之间分配“rooms”。

一对多广播

​ 在这种场景下,单个广播端点(或其中几个广播端点)会产生音频和视频,而服务器后端会将媒体实时流式传输给成百上千的观众(无延迟)。如果有200-300个以上的观众(因此400-600个’consumers’),则可能会超出单个’mediasoup-router’的能力。

为了帮助解决这些情况,mediasoup提供了一种机制,可以使用router.pipeToRouter() API 相互通信不同的mediasoup-routers。

这个概念很简单:

  • 广播者端点将其音频/视频产生(producer1)打到mediasoup的worker1中创建的router1中。
  • 服务器端应用程序在同一主机中创建worker2,worker3等,并在每个worker中创建一个路由器(router2,router3等)。
  • 观众从传输级别连接到那些router2,router3等。
  • 应用程序将producer1 从router1传递到router2以及从router1传递到router3等等。
  • 观众从其各自的routers订阅消费producer1的音视频码流。

也可以使在不同物理主机中运行的mediasoup-router相互通信。但是,由于mediasoup不提供任何信令协议,因此应由应用程序来实现所需的信息交换以实现该目标。作为一个很好的参考,为了将producer通过管道传送到不同主机中的routers,应用程序应实现类似于router.pipeToRouter()方法已经执行的操作,但要考虑到在这种情况下,两个routers都不能协同工作在同一主机host中,因此网络信令是必须的。

当向许多观众(数百或数千个producers)广播视频流时,重要的是要意识到视频RTP传输通常是如何工作的:

  • 观看者最终可能会丢失视频数据包,因此会向mediasoup请求丢包重传。重传是按transport处理的(它们不到达广播端点),因此这里没有限制。
  • 观看者可能会连接或重新连接,或者可能更改其首选的空间层,或者可能会丢失太多数据包。这些情况中的任何一种都意味着有视频关键帧请求通过RTCP-PLI或FIR到广播端点。
  • 一旦接收到视频PLI或FIR后,广播端点中的编码器会生成视频关键帧,该视频关键帧是比常规视频包大得多的视频包。
  • 如果编码器接收到许多PLI或FIR(尽管mediasoup通过限制每秒接收不超过一个的PLI或FIR来保护producer-endpoint),则广播端点的发送比特率将增加2倍或3倍。对于producer-endpoint以及对于每秒将接收更多比特的观众来说,这可能是个问题。
    • *注意:*这可以通过增加默认的keyFrameRequestDelay值来缓解,但是这会导致更长的“黑屏”时间(因为后进入的关键帧可能会被延迟发出,出图像就慢)。
  • 这就是问题所在。

在这些情况下,服务器端需要“重新编码器”。这是一个端点,它消费广播者端点的流,对这些流进行重新编码,并将它们重新生成到一组总共有数百或数千个consumers 的mediasoup路由器中。由于这种“重新编码器”通常在后端网络中运行,因此不受可用带宽的限制。

最后,这些方案需要一个适当的体系结构,使观众跨多个Mediasoup-routers(在相同或不同主机中)分布,并在后端使用特殊的“重新编码器”端点,以承受这些观众发出的PLI和FIR 。

mediasoup提供libmediasoupclient,可以用作重新编码器(wink,wink)。

mediasoup v3设计

与其他现有SFU实现不同,mediasoup不是独立服务器,而是可以集成到更大应用程序中的不受限制的Node.js模块:

const mediasoup = require("mediasoup");

因此,在内部,mediasoup可以分为两个独立的组件:

  • 一个JavaScript层,公开了适用于Node.js的现代ECMAScript(ES核心标准) API,以及
  • 一组处理媒体层(ICE,DTLS,RTP等)的C / C ++子过程。

两个组件通过进程间通信相互通信。但是,从开发人员的角度来看,应用程序应该只关心JavaScript API集成。

特征

  • ECMAScript低级API。

  • 多流:通过单个ICE (交互式连接建立)+ DTLS()传输的多个音频/视频流。(见下图)

  • IPv6就绪。

  • UDP / TCP上的ICE / DTLS / RTP / RTCP。

  • Simulcast联播和SVC支持。 介绍

  • 拥塞控制。

  • 使用空间/时间层分布算法的Sender 和receiver带宽估计。

  • 极其强大(在libuv之上用C ++编码的媒体工作程序子进程)(见下图)

mediasoup中文文档(本人尝试翻译,后续陆续更新)
mediasoup中文文档(本人尝试翻译,后续陆续更新)

架构

mediasoup中文文档(本人尝试翻译,后续陆续更新)
待更新。。。。。。。。。。。。