25 | 那些常见的流媒体服务器,你该选择谁?

上一篇文章中,我们详细讨论了三种类型(Mesh、MCU和SFU)的多方通信架构,并从中知道SFU方案是目前最优的一种多方通信架构方案,而且这种方案目前已经有很多开源的实现了,比较流行的开源项目包括 Licode、Janus-gateway、MediaSoup、Medooze等。

当然,你也可以自己实现SFU流媒体服务器,但自已实现流媒体服务器困难还是蛮多的,它里面至少要涉及到 DTLS 协议、ICE协议、SRTP/SRTCP协议等,光理解这些协议就要花不少的时间,更何况要实现它了。

而使用开源的流媒体服务器就可以大大地减少你的工作量,但这也带来一个问题:这么多开源流媒体服务器,究竟该选哪一个呢?这就涉及到一个选型的问题,你必须要对上面提到的开源项目有个清楚的认知,知道它们各自的优劣点,才能选出更适合的那款流媒体服务器。

接下来我们就按顺序把这几个开源实现向你做下介绍,从而让你了解它们的优缺点,以便选出更适合你的那款流媒体服务器。

Licode

Licode 既可以用作 SFU 类型的流媒体服务器,也可以用作 MCU 类型的流媒体服务器。一般情况下,它都被用于 SFU 类型的流媒体服务器。

Licode 不仅仅是一个流媒体通信服务器,而且还是一个包括了媒体通信层、业务层、用户管理等功能的完整系统,并且该系统还支持分布式部署。

Licode 是由 C++ 和 Node.js 语言实现。其中,媒体通信部分由 C++ 语言实现,而信令控制、用户管理、房间管理用 Node.js 实现。它的源码地址为:https://github.com/lynckia/licode 。下面这张图是 Licode 的整体架构图:

Licode架构图

通过这张图你可以看出,Licode从功能层面来讲分成三部分,即 Nuve 、ErizoController和ErizoAgent 三部分,它们之间通过消息队列进行通信。

  • Nuve 是一个 Web 服务,用于管理用户、房间、产生 token以及房间的均衡负载等相关工作。它使用 MongoDB 存储房间和token信息,但不存储用户信息。
  • ErizoController,用于管理控制,信令和非音视频数据都通过它接收。它通过消息队列与 Nuve进行通信,也就是说 Nuve 可以通过消息队列对 ErizoController 进行控制。
  • ErizoAgent,用于音视频流媒体数据的传输,可以分布式布署。ErizoAgent 与 ErizoController的通信也是通过消息队列,信令消息通过 ErizoController 接收到后,再通过消息队列发给 ErizoAgent,从而实现对 ErizoAgent 进行控制。

通过上面的描述,你可以知道 Licode 不仅仅是一个SFU流媒体服务器,它还包括了与流媒体相关的业务管理系统、信令系统、流媒体服务器以及客户端 SDK等等,可以说它是一个比较完善的产品。

如果你使用 Licode 作为流媒体服务器,基本上不需要做二次开发了,所以这样一套系统对于没有音视频积累的公司和个人具有非常大的诱惑力。目前 Intel CS 项目就是在 Licode 基础上研发出来的,已经为不少公司提供了服务。

但Licode也有以下一些缺点:

  • 在Linux下目前只支持 Ubuntu 14.04版本,在其他版本上很难编译通过。
  • Licode 不仅包括了 SFU,而且包括了 MCU,所以它的代码结构比较重,学习和掌握它要花不少的时间。
  • Licode的性能一般, 如果你把流媒体服务器的性能排在第一位的话,那么Licode就不是特别理想的 SFU 流媒体服务器了。

Janus-gateway

Janus 是一个非常有名的WebRTC流媒体服务器,它是以 Linux 风格编写的服务程序,采用 C 语言实现,支持 Linux/MacOS 下编译、部署,但不支持 Windows 环境。

它是一个开源项目,其源码的编译、安装非常简单,只要按GitHub上的说明操作即可。源码及编译手册的地址为:https://github.com/meetecho/janus-gateway

Janus 的部署也十分简单,具体步骤详见文档,地址为:https://janus.conf.meetecho.com/docs/deploy.html

下面我们来看一下 Janus 的整体架构,其架构如下图所示:

Janus架构图

从上面的架构图中,你可以看出 Janus 分为两层,即应用层传输层

插件层又称为应用层,每个应用都是一个插件,可以根据用户的需要动态地加载或卸载掉某个应用。插件式架构方案是非常棒的一种设计方案,灵活、易扩展、容错性强,尤其适用于业务比较复杂的业务,但缺点是实现复杂,成本比较高。

在 Janus 中默认支持的插件包括以下几个。

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

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

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

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

如果说Janus 有什么缺点的话,那就是它的架构设计比较复杂,对于初学者来说难度较大。

Mediasoup

Mediasoup 是推出时间不长的 WebRTC 流媒体服务器开源库,其地址为:https://github.com/versatica/mediasoup/

Mediasoup 由应用层数据处理层组成。应用层是通过Node.js 实现的;数据处理层由 C++ 语言实现,包括DTLS协议实现、ICE协议实现、SRTP/SRTCP协议实现、路由转发等。

下面我们来看一下 Mediasoup 的架构图,如下所示:

Mediasoup架构图

Mediasoup 把每个实例称为一个 Worker,在 Worker 内部有多个 Router,每个 Router 相当于一个房间。在每个房间里可以有多个用户或称为参与人,每个参与人在Mediasoup中由一个 Transport代理。换句话说,对于房间(Router)来说,Transport 就相当于一个用户。

Transport有三种类型,即 WebRtcTransport、PlainRtpTransport和PipeTransport。

  • WebRtcTransport 用于与 WebRTC 类型的客户端进行连接,如浏览器。
  • PlainRtpTransport 用于与传统的 RTP 类型的客户端连接,通过该 Transport 可以播放多媒体文件、FFmpeg的推流等。
  • PipeTransport 用于 Router 之间的连接,也就是一个房间中的音视频流通过PipeTransport传到另一个房间。

在每个 Transport 中可以包括多个 Producer 和 Consumer。

  • Producer 表示媒体流的共享者,它又分为两种类型,即音频的共享者和视频的共享者。
  • Consumer 表示媒体流的消费者,它也分为两种类型,即音频的消费者和视频的消费者。

Mediasoup的实现逻辑非常清晰,它不关心上层应用该如何做,只关心底层数据的传输,并将它做到极致。

Mediasoup 底层使用 C++ 开发,使用 libuv 作为其异步IO事件处理库,所以保证了其性能的高效性。同时它支持了几乎所有 WebRTC 为了实时传输做的各种优化,所以说它是一个特别优秀的 WebRTC SFU 流媒体服务器。

它与 Janus 相比,它更聚焦于数据传输的实时性、高效性、简洁性,而 Janus 相比 Mediasoup 做的事儿更多,架构和逻辑也更加复杂。所以对于想学习WebRTC 流媒体服务器源码的同学来说,Mediasoup是一个非常不错的项目

另外,对于开发能力比较强的公司来说,根据自己的业务需要在 Mediasoup 上做二次开发也是非常值得推荐的技术方案。

Medooze

Medooze 是一款综合流媒体服务器,它不仅支持 WebRTC 协议栈,还支持很多其他协议,如 RTP、RTMP等。其源码地址为:https://github.com/medooze/media-server

下面我们来看一下 Medooze 的架构图:

Medooze架构图

从大的方面来讲,Medooze 支持 RTP/RTCP、SRTP/SRCP 等相关协议,从而可以实现与 WebRTC终端进行互联。除此之外,Medooze还可以接入RTP流、RTMP流等,因此你可以使用GStreamer/FFmpeg向Medooze推流,这样进入到同一个房间的其他 WebRTC 终端就可以看到/听到由 GStream/FFmpeg 推送上来的音视频流了。另外,Medooze 还支持录制功能,即上图中的 Recorder 模块的作用,可以通过它将房间内的音视频流录制下来,以便后期回放。

为了提高多方通信的质量,Medooze 在音视频的内容上以及网络传输的质量上都做了大量优化。关于这些细节我们这里就不展开了,因为在后面的文章中我们还会对 Medooze 作进一步的讲解。

以上我们介绍的是 Medooze的核心层,下面我们再来看看Medooze的控制逻辑层。Medooze 的控制逻辑层是通过 Node.js 实现的,Medooze 通过 Node.js 对外提供了完整的控制逻辑操作相关的 API,通过这些 API 你可以很容易的控制 Medooze 的行为了。

通过上面的介绍,我们可以知道 Medooze 与 Mediasoup 相比,两者在核心层实现的功能都差不多,但Medooze的功能更强大,包括了录制、推RTMP流、播放 FLV 文件等相关的操作,而Mediasoup则没有这些功能。

不过 Medooze 也有一些缺点,尽管 Medooze 也是 C++ 开发的流媒体服务务器,使用了异步 IO 事件处理机制,但它使用的异步 IO 事件处理的 API 是 poll,poll 在处理异步 IO 事件时,与Linux下最强劲的异步IO事件API epoll 相比要逊色不少,这导致它在接收/发送音视频包时性能比Mediasoup要稍差一些。

如何选择 SFU

上面我们对Licode、Janus、Mediasoup、Medooze 这几个开源的 WebRTC 流媒体服务器做了比较,从中你应该对它们的架构和特性有了一个基本了解。整体上看这些流媒体服务器各有优缺点,对于我们来说到底该选择那个项目作为我们的流媒体服务器呢?

其实,对流媒体服务器的选择是一个 Balance,没有最好,只有最合适。每个开源实现都有其各自的特点,都可以应用到实际产品中,只不过作为开发人员都有自己独特的技术背景,你需要根据自身特点以及项目特点选一个最合适的。接下来,我就介绍一下我是如何对这些开源项目进行评判和选择的。

在选择之前我会像上面一样对要选择的项目有个大体的了解,然后通过以下几个方面来对项目进行打分,从而选出最适合我的项目。

首先是实现语言。在一个团队中肯定会选择一种大家都比较熟悉的语言作为项目开发的语言,所以我们在选择开源项目时,就要选择使用这种语言开发的开源项目。比如阿里系基本都用 Java 语言进行开发,所以它们在选择开源项目时,基本都会选择 Java开发的开源项目;而做音视频流媒体服务的开发人员,为了追求性能,所以一般都选择 C/C++ 语言开发的开源项目。

Meooze、Mediasoup、Licode 这三个流媒体服务器的媒体通信部分都是由 C++ 实现的,而控制逻辑是通过 Node.js 实现,因此如果你是C++开发人员,且有 JavaScript 技术背景,那么你就应该在这三种流媒体服务器之间选择,因为这样更容易入门。而Janus-gateway 是完全通过 C 语言实现的,服务部署是传统的 Linux 风格,因此如果你是 Linux/C 开发者,则应该选择 Janus 作为你的流媒体服务器。

其次是系统特点。像Licode 是一个完整的系统,支持分布式集群部署,所以系统相对复杂,学习周期要长一些。它可以直接布署在生产环境,但是二次开发的灵活性不够。Janus-gateway 是一个独立的服务,支持的信令协议很丰富,而且支持插件开发,易扩展,对于 Linux/C 背景的开发者是很不错的选择。Medooze 和 Mediasoup 都是流媒体服务器库,对于需要将流媒体服务器集成到自己产品中的开发者来说,应该选择它们。

另外,从性能方面讲,Licode、Meooze、Mediasoup、Janus-gateway 单台服务都可以支持500 方参会人,所以它们的性能都还是不错的。相对来说,Licode的性能与其他流媒体服务器相比要低一些;Medooze 由于没有使用epoll来处理异步IO事件,所以性能也受到一些影响。不过总的来说,它们在500方的容量下,视频质量都可以得到很好的保证,延迟在 100ms左右。

小结

本文我向你介绍了 Licode、Meooze、Mediasoup、Janus-gateway 四个开源 SFU 的架构及其特点。

从 SFU 模型来看,它们的实现基本都类似的,只是概念叫法不同,它们之间的差异主要体现在系统对外提供的接口上。对于想要研究 SFU 基本原理的开发者来说,只要选择其中一个项目仔细研读即可。但我个人还是建议初学者选择 Mediasoup 作为研究SFU原理的对象,因为它结构简单,代码量少,很容易入门。当然如果你是一个纯 C 技术背景的开发者,可以选择 Janus-gateway作为研究对象。

如果说还需要研究录制回放、MCU 的开发者,可以去研究 Medooze。Medooze 结构比较完整,功能齐全,代码量也不大。而如果你想要让自己的媒体服务器支持集群部署,可以参考 Licode。

思考时间

如果让你自己实现一个 SFU 流媒体服务器,你会怎么设计?你认为都有哪些问题是实现SFU的关键呢?

欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。

精选留言

  • 大魔王

    2019-11-14 10:32:49

    老师请问一台服务器支持500方人,意思就是一台服务器只能服务一个500人的会议? 那如果是一个平台的话 有很多会议就得很多台服务器了吧
    作者回复

    是这个道理。但有一个问题可能是你没想清楚的,为什么一台流媒体服务只能支持 500 方?为什么台 nginx 服务可以支持 10万人,而流媒体服务器却只有 500 人呢?它的瓶颈点是什么你要弄清楚?

    2019-11-15 09:11:59

  • 晓峰

    2022-07-12 15:35:50

    老师,没有对列举 SRS 是什么原因呢?不适合还是不推荐?
  • 陈陳

    2020-10-29 20:48:34

    作为一名Javaer,是不是告别了流媒体了。。
    作者回复

    Java开发流媒体服务器性能上还是有点差,即使有点流媒体服务器说是Java开发的,但底层还是用的JNI/C++

    2020-11-10 18:16:57

  • 嗨諾

    2020-06-08 15:28:08

    老师,您好,最近自己在搭建kurento 客户端和服务端。搭建服务端的时候需要搭coturn,现在这个服务一直有问题,穿透不成功。请问TURN服务必须要两个公网IP吗?
    作者回复

    不太清楚kurento是怎么运转的。网上有很多资料是错误的,比如有人说Janus必须要有 turn 服务才能运行,这是很荒谬的,这些人根据没有好好阅读Janus文档,也没有对它做个深入研究。作为WebRTC流媒体服务器来说,它本身就是一个turn服务。

    你是否对kurento理解正确了呢?

    2020-06-23 10:20:58

  • 三角形小于零

    2019-09-11 08:21:30

    老师,后面会讲 turn server吗
    作者回复

    turn服务是 1对1的,那个没啥要讲的呀!你是想实现多对多吧?如果是这样的话,后面几篇文章是专门讲这个的。

    2019-09-11 17:46:19

  • 仰泳鱼

    2021-10-08 16:17:07

    老师您好,请问这个单台500方会议是指都开了摄像头和麦克风吗?(虽然没有这样的会议,一个电脑屏幕也放不下那么多大头啊,除了巨幅屏),那请问如果500方连接,其中只有几个领导开摄像头和麦克风,其他只是观看收听,是不是可以支持更多。
  • 波波安

    2020-06-29 21:56:31

    我用的kurento流媒体,单台服务器只能拉20方h264流 cpu干到90%,服务器做了转码。您说的单台500是没有做转码么
    作者回复

    对,服务器不做转码

    2020-07-02 11:57:36

  • tokamak

    2019-09-10 06:32:23

    老师,你好。RTSP协议在安防监控领域应用很广泛,而且RTSP协议用UDP负载RTP包,实时性比较好。与RTMP/HLS相比,为什么RTSP协议在互联网领域应用很少呢?
    作者回复

    因为 RTMP/HLS 底层用的是 TCP 协议,这样就不用考虑丢包情况了。

    RTSP 数据是用的 UDP,控制是它自己的一套,实际上与 SIP协议很类似的。但现在大家更多的是使用 WebRTC, RTSP 和 SIP 用的都比较少,只是在专有领域才会用。

    2019-09-10 12:14:03

  • 罗志军

    2020-04-10 10:07:24

    老师,请问下我就想通过手机客户端查看流(局域网IPC)就好了,是不是只需要turn就行了?
    作者回复

    如果是 1:1的就可以用turn服务,如果是多对多你要用medooze, mediasoup, janus之类的流媒体服务器

    2020-04-18 23:03:49

  • Hadooper

    2020-01-09 14:55:26

    medooze已经好几年没有主要功能维护了,不知道老师怎么评价jitsi和kurento这两个依旧持续维护的框架?
    作者回复

    大的功能都已经完成了,不需要做大的改动了。目前medooze一直在不断更新。jitsi是java版本的,底层也是用 C++实现的,我没有看它的代码,不好评价。

    2020-01-14 23:22:20

  • 杨武

    2019-12-28 01:26:49

    现用的是streamedian,实现rtsp流的web端播放,但是无法支持4k高清,h265,并且经常会有性能问题,浏览器崩溃卡死,请问老师有什么建议么
    作者回复

    4K 高清对于编解码的性能要求还比较高,目前不太适合在浏览器上使用

    2020-01-14 23:24:12

  • tkly

    2019-12-19 10:16:27

    我的要求并不高,我只想实现一个rtsp/rtmp/file等接入,通过webrtc实现网页无插件播放h264视频的方案,该如何搞?
    作者回复

    通过流媒体服务端就可以实现,mediasoup就是一个现成的方案!

    2019-12-22 22:22:00

  • 牛景波

    2019-09-10 07:50:40

    sfu核心就是简单和快,转发上用共享内存,无锁队列,消息队列是不能用了;收发包可以用dpdk加速,降低cpu消耗
    作者回复

    不错!在 Licode中虽然你看到它用了 RabbitMQ, 但它是信令消息才会用,对于流媒体数据它是不会使用 MQ的哈

    2019-09-10 12:20:26

  • ifelse

    2025-07-30 12:31:17

    学习打卡
  • keepgoing

    2025-04-29 17:14:39

    老师 https://github.com/medooze/media-server 地址已经 404 了,请问最新的开源项目是在哪里呀
  • 白小菜

    2022-09-26 19:38:05

    如果不要流媒体服务器,只要一个信令服务器加上管理peer节点,一个人播放,像一个链表一样,peer节点依次往后连接,可行吗?不考虑进进出出的情况
  • 代先生。

    2022-04-29 15:32:38

    ZLMediaKit不作为推荐吗
  • CaptainJack

    2022-01-13 08:44:26

    老师好,最近打算学些mediasoup,发现服务器上无法安装编译成功,服务器是阿里云ECS ubuntu 20,安装源也改成淘宝的了,但是好像有些依赖timeout,怎么着都装不上,求助
  • Geek_49705f

    2020-08-03 11:02:49

    你好,早阿里云上搭建mediasoup-demo服务器,然后手机上可以看到自己的画面,但是相同房间内看不到别人的画面,对方也不到自己的,暂时没有找到什么原因
    。帮我分析下,这个大致是什么原因
    作者回复

    medooze demo?还是mediasoup demo?是房间里的人都彼此看不到还是都看不到某个人的视频?

    2020-08-06 13:27:09

  • Geek4329

    2020-06-23 03:44:14

    老师您好!我们是做一个客服使用的远程控制+远程控制应用(1对1),要求比较高的实时性,同时要能支持录制回放,是否选用mediasoup比较合适?
    另外想请教一下,对于运营商可能封禁udp的问题怎么处理?
    作者回复

    mediasoup应该是几个流媒体服务器中性能最好的一个。WebRTC本身是支持 UDP 和 TCP的

    2020-06-23 09:53:00