13、MCU服务器搭建:基于Janus的MCU部署、视频混流与录制、插件机制

聊到WebRTC的多人通信,大家第一个想到的肯定是SFU。没错,SFU是目前的主流方案。但有些场景,比如大型直播、多人会议需要统一录制、或者客户端性能有限时,MCU方案反而更合适。

今天我们就来聊聊Janus这个开源MCU服务器。我最早接触Janus是在2017年,当时一个项目需要在浏览器端做多方视频通话,还要把所有人的画面合成一路录制下来。嗯,SFU搞不定这个,最后选了Janus。

13.1 Janus是什么?

Janus是一个轻量级的WebRTC网关,由Meetecho团队开发。它本身不只是一个MCU,更像是一个插件化的WebRTC服务器框架。

说白了,Janus的核心就是一个消息路由器和媒体转发引擎。它把各种功能拆成了插件,比如视频会议、流媒体播放、录音桥等。你需要什么功能,就加载什么插件。

核心特点:

  • 插件架构,功能可扩展
  • 支持MCU和SFU两种模式
  • 内置视频混流(VideoRoom插件)
  • 支持录制到文件
  • RESTful API控制

我个人习惯把Janus比作瑞士军刀。它不追求极致性能,但胜在功能全面、部署简单。很多中小型项目用它做原型验证,非常方便。

13.2 Janus的架构与部署

先看看Janus的整体架构。我画了一张图,帮你快速理解它的工作方式。

Janus MCU 架构图 浏览器 A 浏览器 B 浏览器 C Janus 核心 消息路由 媒体转发 会话管理 插件加载器 插件层 VideoRoom 插件 AudioBridge 插件 RecordPlay 插件 混流输出 / 录制文件

部署Janus其实不复杂。我建议用Docker方式,省去编译的麻烦。

# 拉取Janus镜像
docker pull canyan/janus-gateway:latest

# 运行Janus容器
docker run -d --name janus \
  -p 8088:8088 \
  -p 8188:8188 \
  -p 10000-10200:10000-10200/udp \
  canyan/janus-gateway:latest

这里要注意端口映射:

  • 8088:HTTP管理接口
  • 8188:WebSocket接口
  • 10000-10200:媒体端口(UDP)

小技巧:我在项目中习惯把媒体端口范围设大一点,比如10000-20000。因为多人会议时端口消耗很快,曾经遇到过端口不够用导致新用户连不上的情况。

13.3 VideoRoom插件:视频混流

VideoRoom是Janus最核心的插件。它实现了MCU模式下的视频混流功能。

什么叫混流?就是把多个人的视频画面合成一路视频流。比如4个人开会,每个人的画面被缩小后拼成一个2x2的格子,然后编码成一路视频发给所有参与者。

这样做的好处很明显:

  • 客户端只需要解码一路视频,CPU消耗低
  • 录制方便,直接录混流后的画面就行
  • 带宽占用小,适合移动端

但缺点也有:

  • 服务器压力大,需要做视频解码、合成、再编码
  • 灵活性差,不能单独看某一个人的画面

我曾经在一个在线教育项目里用过这个方案。老师端只需要显示一路视频,里面包含了所有学生的画面。嗯,效果还不错,学生端的手机也不发烫。

13.3.1 创建视频房间

通过Janus的REST API创建房间:

POST /janus/<session_id>/<handle_id>
Content-Type: application/json

{
  "janus": "message",
  "body": {
    "request": "create",
    "room": 1234,
    "description": "我的视频房间",
    "publishers": 6,
    "bitrate": 512000,
    "videocodec": "h264",
    "record": true,
    "rec_dir": "/opt/janus/recordings"
  }
}

参数说明:

参数 说明 我的建议
room 房间ID,唯一标识 用数字,方便管理
publishers 最大发布者数 根据服务器性能定,一般6-8人
bitrate 混流后的码率 512kbps够用,画质要求高可以设1M
videocodec 视频编码器 H.264兼容性最好
record 是否录制 开启后自动录混流视频

注意:如果开启录制,一定要确保rec_dir目录存在且有写入权限。我曾经因为忘记创建目录,导致录制功能静默失败,排查了半天才发现是目录问题。

13.3.2 混流布局配置

Janus支持多种混流布局。你可以通过配置来调整:

{
  "request": "configure",
  "video_orientation": 1,
  "video_orientation_force": true,
  "videomulticast": false,
  "videocodec": "h264",
  "bitrate": 512000,
  "record": true,
  "filename": "meeting_2024"
}

布局模式有几种:

  • 自动布局:根据人数自动排列,1人全屏,2人左右分屏,4人2x2
  • 固定布局:指定某个人为主画面,其他人缩小在角落
  • 自定义布局:通过API动态调整每个画面的位置和大小

我个人比较喜欢自动布局,省心。但如果你做的是直播类应用,固定布局更合适,把主讲人放在大画面。

13.4 视频录制

Janus的录制功能非常实用。它会把混流后的视频直接写入文件。

录制文件格式是.mjr(Janus自己的格式),但你可以用工具转成.mp4:

# 安装转换工具
apt-get install janus-tools

# 转换录制文件
janus-pp-rec input.mjr output.mp4

这里有个坑要提醒你:

我曾经踩过的坑:录制文件默认保存在容器内部。如果容器重启,录制文件就丢了。一定要挂载外部目录到容器里。

docker run -d --name janus \
  -v /data/recordings:/opt/janus/recordings \
  -p 8088:8088 \
  -p 8188:8188 \
  -p 10000-10200:10000-10200/udp \
  canyan/janus-gateway:latest

13.5 插件机制详解

Janus的插件机制是它的灵魂。说白了,Janus本身只做两件事:建立WebRTC连接和转发媒体数据。具体业务逻辑全交给插件。

常用的插件有:

插件名 功能 适用场景
VideoRoom 视频会议、混流 多人视频通话
AudioBridge 音频混流 语音会议、电话会议
Streaming 流媒体播放 直播推流、RTSP转WebRTC
RecordPlay 录制与回放 会议录制、回看
SIP SIP网关 对接传统电话系统

如果你想开发自己的插件,Janus提供了C语言接口。不过说实话,开发门槛不低。我建议先用现成的插件组合,实在满足不了需求再考虑自定义插件。

13.6 实战:搭建一个简单的MCU会议

最后,我带你走一遍完整的流程。假设我们要搭建一个4人视频会议,开启录制。

第一步:启动Janus

docker run -d --name janus-mcu \
  -p 8088:8088 \
  -p 8188:8188 \
  -p 10000-20000:10000-20000/udp \
  -v /data/janus-recordings:/opt/janus/recordings \
  canyan/janus-gateway:latest

第二步:创建房间

curl -X POST http://localhost:8088/janus \
  -H "Content-Type: application/json" \
  -d '{
    "janus": "create",
    "transaction": "1"
  }'

拿到session_id后,再创建房间:

curl -X POST http://localhost:8088/janus/<session_id>/<handle_id> \
  -H "Content-Type: application/json" \
  -d '{
    "janus": "message",
    "body": {
      "request": "create",
      "room": 1001,
      "publishers": 4,
      "bitrate": 512000,
      "record": true,
      "rec_dir": "/opt/janus/recordings"
    }
  }'

第三步:客户端加入

客户端通过WebSocket连接到Janus,加入房间1001,发布自己的音视频流。Janus会自动进行混流,并把合成后的视频分发给所有参与者。

经验之谈:第一次测试时,建议先用两个浏览器窗口模拟两个人加入。确认混流和录制都正常后,再逐步增加人数。这样排查问题会快很多。

好了,关于Janus的MCU部署、视频混流和录制,就聊到这里。这套方案虽然不如SFU灵活,但在特定场景下非常实用。尤其是你需要统一录制、或者客户端性能受限时,Janus的MCU模式能帮你省不少事。


公众号:蓝海资料掘金营,微信deep3321