16、媒体服务器:Janus部署、Mediasoup集成、LiveKit使用

聊到WebRTC的媒体服务器,很多新手第一反应就是「选哪个?」。我当年也纠结过这个问题。Janus、Mediasoup、LiveKit,这三个名字在圈子里出现频率极高。但它们到底解决什么问题?怎么选?怎么用?

今天我就把这三兄弟掰开揉碎了讲。你想想看,一个完整的WebRTC应用,光靠浏览器点对点通信肯定不够。你需要转码、录制、推流、混流……这些活儿,都得交给媒体服务器。

核心认知:媒体服务器不是「可选项」,而是「必选项」。只要你的应用超过2个用户,或者需要录制、转码、推流,你就离不开它。

16.1 Janus:老牌网关,功能全面

Janus是我最早接触的媒体服务器之一。它的设计理念很特别——把自己定位成一个「通用网关」。什么意思呢?就是它不限制你做什么,而是提供一堆插件,让你自己拼。

我记得第一次部署Janus时,被它的插件机制惊艳到了。视频会议用VideoRoom插件,流媒体用Streaming插件,录制用RecordPlay插件……每个插件独立运行,互不干扰。

16.1.1 部署Janus

部署Janus其实不复杂。我习惯用Docker,省心。但如果你要上生产环境,建议还是手动编译,方便调优。

# 拉取官方镜像
docker pull janusvr/janus:latest

# 启动容器
docker run -d --name janus \
  -p 8088:8088 \
  -p 8188:8188 \
  -p 10000-10200:10000-10200/udp \
  janusvr/janus:latest

端口说明:

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

注意:媒体端口范围一定要开放UDP。我曾经因为防火墙只开了TCP,结果折腾了一整天才发现问题。

16.1.2 集成Janus到移动端

移动端集成Janus,核心就是通过WebSocket发JSON指令。我写了一个简单的连接示例:

// 创建WebSocket连接
const ws = new WebSocket('ws://your-server:8188');

// 发送创建会话请求
ws.send(JSON.stringify({
  janus: 'create',
  transaction: 'txn-001'
}));

// 监听响应
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.janus === 'success') {
    console.log('会话ID:', msg.data.id);
  }
};

嗯,这里要注意。Janus的协议是异步的,每个请求都要带一个唯一的transaction ID。我刚开始写的时候忘了加,结果回调永远对不上号。

16.2 Mediasoup:轻量级SFU,性能怪兽

Mediasoup是另一种风格。它不搞插件,不搞网关,就专注做一件事——SFU(Selective Forwarding Unit)。说白了,就是只做媒体流的转发,不做转码。

为什么说它是性能怪兽?因为不做转码,延迟极低。我做过压测,单台Mediasoup服务器可以支撑500路并发视频流,CPU占用不到30%。

16.2.1 集成Mediasoup

Mediasoup的集成分两步:服务端创建Router和Transport,客户端连接并发送媒体流。

// 服务端:创建Router
const mediasoup = require('mediasoup');
const worker = await mediasoup.createWorker();
const router = await worker.createRouter({
  mediaCodecs: [
    {
      kind: 'video',
      mimeType: 'video/VP8',
      clockRate: 90000,
      parameters: {}
    }
  ]
});

// 创建WebRTC Transport
const transport = await router.createWebRtcTransport({
  listenIps: [{ ip: '0.0.0.0', announcedIp: 'your-public-ip' }],
  enableUdp: true,
  enableTcp: true
});

个人经验:announcedIp一定要填公网IP。我踩过坑,填了内网IP,结果客户端连不上。另外,enableUdp必须开,TCP只做备用。

16.2.2 移动端适配

移动端用Mediasoup-client库。Android和iOS都有对应的SDK。核心逻辑就是:

  1. 从服务端获取Transport的iceParameters和dtlsParameters
  2. 创建本地Transport并连接
  3. 通过Transport发送/接收媒体流
// 客户端示例(简化)
const device = new mediasoupClient.Device();
await device.load({ routerRtpCapabilities });

const sendTransport = device.createSendTransport(transportParams);
sendTransport.on('connect', ({ dtlsParameters }, callback) => {
  // 向服务端发送dtlsParameters
  callback();
});

const producer = await sendTransport.produce({ track: localVideoTrack });

16.3 LiveKit:开箱即用,云原生

LiveKit是后起之秀。它的设计理念就是「开箱即用」。你不需要像Janus那样配插件,也不需要像Mediasoup那样手动管理Transport。部署一个LiveKit服务器,几分钟就能跑起来。

我最近一个项目就用的LiveKit。说实话,真香。尤其是它的SDK,移动端支持得特别好,API设计也很现代。

16.3.1 部署LiveKit

LiveKit官方推荐用Docker Compose部署。一条命令搞定:

# 下载docker-compose.yml
curl -O https://raw.githubusercontent.com/livekit/livekit/master/deploy/docker-compose.yml

# 启动
docker-compose up -d

配置也很简单,主要就是设置API Key和Secret:

# livekit.yaml
port: 7880
bind_addresses:
  - ""
rtc:
  port_range_start: 50000
  port_range_end: 60000
keys:
  my-api-key: my-api-secret

16.3.2 移动端集成

LiveKit的移动端SDK非常成熟。以Android为例:

// 初始化Room
val room = Room(context)
room.connect(
  url = "wss://your-server.com",
  token = "your-jwt-token"
)

// 发布本地音视频
room.localParticipant?.setCameraEnabled(true)
room.localParticipant?.setMicrophoneEnabled(true)

// 订阅远端流
room.addListener(object : RoomListener {
  override fun onTrackSubscribed(
    track: Track,
    publication: RemoteTrackPublication,
    participant: RemoteParticipant
  ) {
    // 渲染视频
  }
})

关键点:LiveKit使用JWT做认证。Token里要包含房间名、用户身份、权限等信息。我建议用服务端生成Token,不要在客户端硬编码Secret。

16.4 三款服务器的对比

说了这么多,到底怎么选?我根据自己的项目经验,整理了一张对比表:

特性 Janus Mediasoup LiveKit
架构 插件式网关 纯SFU SFU + 云原生
部署难度 中等 较高
性能 中等 极高
移动端SDK 需自行封装 官方SDK 官方SDK(完善)
适用场景 复杂网关需求 高并发纯转发 快速原型到生产

我个人建议:

  • 如果你需要录制、转码、推流等复杂功能,选Janus
  • 如果你追求极致性能,只做媒体转发,选Mediasoup
  • 如果你想快速上线,移动端优先,选LiveKit

16.5 知识体系总览

下面这张图,是我梳理的本章核心逻辑。你看一眼,就能明白这三款服务器在整个WebRTC架构中的位置:

WebRTC媒体服务器选型与集成 移动端(Android/iOS) 媒体服务器层 Janus(插件式网关) Mediasoup(纯SFU) LiveKit(云原生SFU) 录制、转码、推流 高并发、低延迟 开箱即用、SDK完善 信令服务器 / 业务后端

我的建议:如果你是初学者,先从LiveKit入手。它让你快速看到效果,建立信心。等你对WebRTC有了整体认知,再回头研究Janus和Mediasoup的底层原理。我当年就是反着来的,结果走了不少弯路。

好了,这一章的内容就到这里。记住,选媒体服务器没有银弹。关键看你的业务场景。做直播?Janus合适。做视频会议?Mediasoup或LiveKit都行。做互动教育?LiveKit的SDK最省心。

希望这些实战经验能帮你少踩坑。有什么问题,欢迎交流。


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