WebRTC视频通话技术选型报告

1 Mediasoup(备选)

详情介绍:

开源协议:MIT

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

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 表示媒体流的消费者,它也分为两种类型,即音频的消费者和视频的消费者。

6

拥有以下特性:

  • 在服务器端是一个Node.js模块
  • 在客户端是一个小的SDK

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

重要功能 评分 1-5 评价
支持IPV6
ICE/DTLS/RTP/RTCP 既可以在TCP协议上运行也可以在UDP协议上运行
支持Simulcast(多流发送) 和 SVC(分层接收)
支持拥塞控制
带宽评估
支持STCP协议(非音视频数据 如文件,文本数据)
多路使用同一个 ICE + DTLS 传输通道 (减少端口的占用)
拥有强大的性能(底层是C++ 使用进程+LIBUV 异步I/O实践处理机制)
5 很丰富
文档&开发指引 评分 1-5 评价
github有8个官方demo
官网有较详细API文档
国内开发文档较少
3 较少
环境搭建 评分 1-5 评价
按官方指引只能本地build,需安装node、python、gcc等编译环境,较复杂
不支持docker构建
2 较难
服务端&客户端开发 评分 1-5 评价
仿照demo进行js开发 2 单一
功能扩展 评分 1-5 评价
按照文档实现应用层逻辑即可 4 较容易
性能 评分 1-5 评价
得益于其优秀的架构设计,性能在几个选型目标中处于一流水平 5 很强

总结:

优点:架构清晰简单,代码很新,性能很强

缺点:服务器端和终端(web+移动端)都是js开发

2 Kurento(备选)

详情介绍:

开源协议: Apache 2.0

Kurento是一个著名的WebRCT流媒体服务器,通过客户端API为网页和手机平台更轻松的开发高级的视频程序,Kurento包括组通信、转码、录制、混淆、广播和路由音视频流。它是采用C和C++语言实现的,支持 Java和JavaScript两种语言的客户端实现。

按分层的方式来划分,Kurento应用可以分为三层(类似于典型的Web应用):

  1. 展现层 —— 浏览器、移动应用、其它媒体源等应用客户端:

    基于任意协议和应用逻辑层通信,发起信号处理

    基于RTP/HTTP/WebRTC协议和KMS通信

    通过KMS的输入端点,传输媒体流到KMS

    通过KMS的输出端点,从KMS获得媒体流

  2. 应用逻辑层——应用服务器负责信号平面:

    基于WebSocket/HTTP/REST/SIP等方式和应用客户端通信,进行信号处理

    内嵌Kurento Client,基于Kurento Protocol与KMS通信,管理媒体元素/媒体管线

  3. 服务层——KMS负责媒体平面,可以对输入流进行各种处理,并产生输出流

    7
    8

java实例(HelloWorld)

// 创建媒体管线
MediaPipeline pipeline = kurento.createMediaPipeline();
// 在管线中添加一个WebRTC端点
WebRtcEndpoint webRtcEndpoint = new WebRtcEndpoint.Builder(pipeline).build();
// 连接WebRTC端点到自己
webRtcEndpoint.connect(webRtcEndpoint);
 
// 创建一个用户会话(UserSession不属于KMS 客户端API的组成部分)
UserSession user = new UserSession();
// 连接到的管线
user.setMediaPipeline(pipeline);
// 连接到的端点,注意此端点的输入、输出是同一个流
user.setWebRtcEndpoint(webRtcEndpoint);
// 以WebSocket会话标识时别用户https://localhost:8443/#
users.put(session.getId(), user);
 
// 处理SDP
String sdpOffer = jsonMessage.get("sdpOffer").getAsString();
// 由端点来处理SDP,生成应答
String sdpAnswer = webRtcEndpoint.processOffer(sdpOffer);
// 以消息类型startResponse将应答SDP通过WebSocketSession发回给客户端
JsonObject response = new JsonObject();response.addProperty("id", "startResponse");
response.addProperty("sdpAnswer", sdpAnswer);
synchronized (session) {
    session.sendMessage(new TextMessage(response.toString()));
}
 
// 一旦收集到服务器的ICE候选信息,即以消息类型iceCandidate发送给客户端
webRtcEndpoint.addIceCandidateFoundListener(new EventListener<IceCandidateFoundEvent>() {
  @Override
  public void onEvent(IceCandidateFoundEvent event) {
    JsonObject response = new JsonObject();
    response.addProperty("id", "iceCandidate");
    response.add("candidate", JsonUtils.toJsonObject(event.getCandidate()));
    try {
      synchronized (session) {
        session.sendMessage(new TextMessage(response.toString()));
      }
    } catch (IOException e) {
      log.error(e.getMessage());
    }
  }
});
// 为某个端点收集服务器的ICE候选信息
webRtcEndpoint.gatherCandidates();

在这个HelloWorld例子中,媒体流不是简单的由客户端发给自己,而是由服务器中转。也就是说,通信的Peer是服务器、客户端。

重要功能 评分 1-5 评价
支持HTTP, RTP and WebRTC
群组通信,SFU,MCU,混流,路由、分发
滤镜、虚拟现实增强
WebM and MP4 存储录制视频
GStreamer流 支持,包括 VP8, H.264, H.263, AMR, OPUS, Speex, G.711
5 很丰富
文档&开发指引 评分 1-5 评价
github有18个官方demo
官网有很详细API文档
国内开发文档较少
4 英文文档很丰富
中文文档匮乏
环境搭建 评分 1-5 评价
按官方指引Ubuntu环境下构建
支持docker构建较方便
4 容易
服务端&客户端开发 评分 1-5 评价
仿照demo进行js或java开发
java开发demo为SpringBoot工程,阅读较方便
4 较丰富
功能扩展 评分 1-5 评价
按照文档实现插件开发 4 较容易
性能 评分 1-5 评价
Kurento在性能上弱于其它产品,在同时在线人数小于50人时性能比较稳定 3 较强

总结:

优点:功能强大,扩展方便,可以用java开发服务端

缺点:性能第二档水平,单独部署KMS服务器不如Mediasoup方便

3 Jitsi(不推荐)

简介:

开源协议: Apache 2.0

Jitsi 视频桥是 XMPP 服务器组件,允许多用途视频通信。Jitsi 视频桥不能将视频频道混合到复合视频流中,只会将接收的视频频道中继给所有呼叫参与者,不具有视频混流能力。

不推荐理由:

开发文档不足,项目开发环境编译不成功,需要连接外网编译下载依赖。功能不能覆盖需求。

4 Janus-gateway(不推荐)

简介:

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

janus基于插件思想,通过实现基础架构,完成了与浏览器链接的建立过程。

janus的插件主要完成一些必须的函数实现,如RTP/RTCP数据的接收。

我们通过实现自己的插件,来完成在将浏览器RTP数据转发到内网服务器的业务逻辑。

3
4

js开发:提供janus.js的API库

插件开发:C风格头文件方法实现

    struct janus_plugin {

    int (* const init)(janus_callbacks *callback, const char *config_path);

    void (* const destroy)(void);

    int (* const get_version)(void);

    const char *(* const get_package)(void);

    void (* const create_session)(janus_plugin_session *handle, int *error);

    struct janus_plugin_result * (* const handle_message)(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep);

    void (* const setup_media)(janus_plugin_session *handle);

    void (* const incoming_rtp)(janus_plugin_session *handle, int video, char *buf, int len);

    void (* const incoming_rtcp)(janus_plugin_session *handle, int video, char *buf, int len);

    void (* const incoming_data)(janus_plugin_session *handle, char *buf, int len);

    void (* const destroy_session)(janus_plugin_session *handle, int *error);

    ...

    };

不推荐理由:

插件开发技术栈不适合

5 Licode(不推荐)

简介:

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

Licode 是由 C++ 和 Node.js 语言实现。其中,媒体通信部分由 C++ 语言实现,而信令控制、用户管理、房间管理用 Node.js 实现

1

不推荐理由:

Licode是一个完整的系统,内置MangoDB、RabbitMQ,系统相对复杂,学习周期要长一些。它能够直接布署在生产环境,可是二次开发的灵活性不够(没法用java写业务逻辑)

6 Medooze(不推荐)

简介:

Medooze 的功能十分强大,通过它你既可以实现 SFU 类型的流媒体服务器,也可以实现 MCU 类型的流媒体服务器。而且,它还支持多种媒体流接入

Medooze 的整体架构与 Mediasoup 类似,不过它的信令处理、业务管理以及媒体数据的转发功能都是放在 Nodejs下进行统一管理的。实际上,这样的管理方式也不会对性能造成什么影响,因为重的媒体流的转发工作仍然是使用的 C++ 在 Nodejs 底层实现的

2
5

不推荐理由:

与Mediasoup相比没有明显优势,业务逻辑没有Mediasoup清晰、没有进程管理,底层使用的poll来处理I/O事件不如Mediasoup的libuv