mediasoup
基本概念
v3版本源码实现了SFU的基本转发功能,由C++部分的worker和TS部分的信令组成。这两部分之间用Unix domain socket通信,是进程之间的全双工通信方式,基于文件系统,不需要走协议栈,因此必须同机部署。
peer
逻辑层抽象,代表了通话的成员。
room
逻辑层通常和router绑定,代表了通话的房间。
router
模型层代表了媒体流转发的单元,一个router内包含了transport, producer, consumer这些模型的实例。
记录了transport和流的包含关系,还有producer和consumer的映射关系,主要负责从transport中获取数据包和producer/consumer的流媒体转发。
transport
数据层抽象,代表了一路socket层面的数据流,可以承载多个RTP stream。通常一个典型的通话里,上行和下行需要分别建立两个socket连接,就是两个transport。客户端与mediasoup之间的transport通常是webrtcTransport
。mediasoup之间的routers也可以建立transport实现级联关系,通常是pipeTransport
。发给GStreamer和ffmepg的为plainTransport
。
基于socket的webrtcTransport的ICE只支持Lite模式,一方面是因为作者并非将它设计为商业用途,另一方面mediasoup的STUN把自己也当成一个host,简单实现了协议功能。
producer
媒体流的生产者。
consumer
媒体流的消费者。
源码结构
实现协议
WebRTC实现连接的ICE和能力协商的SDP都属于描述性协议,并不严格规定具体的实现。因此信令层面由mediasoup官方提供的demo和client-cpp,client-js等实现具体基于webrtc的调用,这部分代码主要在demo。数据层则是实现了RTP/RTCP协议的基本传输和反馈能力,这部分代码主要在worker。client-cpp提供了调用webrtc-native的API,client-js则是调用支持webrtc的浏览器端提供的API。client和demo/worker通过私有信令和标准协议通信实现了基本的RTC功能。
动手实现一个Mediasoup client
使用pion提供的webrtc库实现一个可以对接mediasoup的client小工具,使用的语言主要为golang。
建立媒体传输通道
因为mediasoup把SDP拆成了几条信令在websocket上协商,因此需要把SDP中的字段拆解成所需要的字段封装在client端和给mediasoup server。
ICE
从webrtc transport信令中拿到candidate列表,因为mediasoup是lite的ICE,client端是controlling,mediasoup是controlled,只需要从client去建立连接即可。
1 |
|
至此,和webrtctransport的ice连接就建立了一半,接下来在ice的基础上做dtls密钥交换。
DTLS
mediasoup支持双向的dtls连接,dtls之后将密钥导出到ice的connection,对rtp的payload进行加密,媒体数据走的是srtp标准协议。
生成dtls证书和指纹
1 |
|
将dtls指纹参数通过信令发送给mediasoup,然后进行dtls连接即可,dtls可使用server也可以使用client,通过信令参数均可调整。
1 |
|
至此,媒体通道webrtc transport已经建立。
媒体传输
srtp不需要对整个数据包进行加密,因此收发数据仍然是在ice的connection上进行,但是将dtls的密钥导出用于加密每一个rtp的payload。
1 |
|
将RTP包的header和payload分别填入handler即可在之前建立的媒体通道上进行收发媒体。