safesight-edge/docs/architecture/zlmediakit_multi_stream.md

3.6 KiB
Raw Blame History

ZLMediaKit 多路流输出机制

发现背景

在开发 4-5 路并发压测配置时,发现 ZLMediaKit 并非通过多端口监听来实现多路输出,而是通过单端口 + 多路径的方式实现。

机制说明

传统理解(错误)

以为每个 publish 节点需要独立的端口:

cam1 -> port 8555 -> /live/cam1
cam2 -> port 8556 -> /live/cam2
cam3 -> port 8557 -> /live/cam3
cam4 -> port 8558 -> /live/cam4

实际机制(正确)

ZLMediaKit 采用 HTTP-like 虚拟主机机制

Single TCP Server: port 8555
  ├─ path: /live/cam1  -> stream cam1
  ├─ path: /live/cam2  -> stream cam2
  ├─ path: /live/cam3  -> stream cam3
  ├─ path: /live/cam4  -> stream cam4
  └─ path: /live/cam5  -> stream cam5

日志验证

启动 5 路并发时观察到的日志:

# 只启动一次 TCP Server
TcpServer.cpp:200 start_l | TCP server listening on [::]: 8555

# 5 路流共享同一个端口,不同 path
zlm rtsp server ready: rtsp://0.0.0.0:8555/live/cam1
zlm rtsp server ready: rtsp://0.0.0.0:8555/live/cam2
zlm rtsp server ready: rtsp://0.0.0.0:8555/live/cam3
zlm rtsp server ready: rtsp://0.0.0.0:8555/live/cam4
zlm rtsp server ready: rtsp://0.0.0.0:8555/live/cam5

配置示例

错误的配置(端口冲突)

"outputs": [
  { "proto": "rtsp_server", "port": 8555, "path": "/live/cam1" }
]

5 个实例分别配置 8555/8556/8557/8558/8559 会导致资源浪费。

正确的配置(共享端口)

"outputs": [
  { "proto": "rtsp_server", "port": 8555, "path": "/live/${name}" }
]

所有实例使用相同端口,通过 ${name} 变量区分不同路径。

播放地址

基于共享端口机制,客户端播放地址为:

通道 RTSP 地址 HLS 地址
cam1 rtsp://<ip>:8555/live/cam1 http://<ip>:9000/hls/cam1/index.m3u8
cam2 rtsp://<ip>:8555/live/cam2 http://<ip>:9000/hls/cam2/index.m3u8
cam3 rtsp://<ip>:8555/live/cam3 http://<ip>:9000/hls/cam3/index.m3u8
cam4 rtsp://<ip>:8555/live/cam4 http://<ip>:9000/hls/cam4/index.m3u8
cam5 rtsp://<ip>:8555/live/cam5 http://<ip>:9000/hls/cam5/index.m3u8

优势

  1. 端口资源节省 - 无论多少路流,只需 1 个端口
  2. 防火墙友好 - 只需开放 1 个端口
  3. 管理简便 - 统一入口,通过路径区分
  4. 扩展性好 - 理论上支持无限路流(受限于系统资源)

限制

  1. 单进程限制 - ZLMediaKit 实例是单例的,必须在同一个 media-server 进程内
  2. 路径冲突 - 不同流的路径必须唯一
  3. 端口独占 - 8555 被占用后,其他进程无法使用

相关配置

多路并发压测配置示例:configs/stress_5ch_cam4_template.json

关键配置片段:

{
  "templates": {
    "strict_minio_alarm_pipeline": {
      "nodes": [
        {
          "id": "pub",
          "type": "publish",
          "outputs": [
            { "proto": "rtsp_server", "port": 8555, "path": "/live/${name}" },
            { "proto": "hls", "path": "./web/hls/${name}/index.m3u8" }
          ]
        }
      ]
    }
  },
  "instances": [
    { "name": "cam1", "template": "strict_minio_alarm_pipeline" },
    { "name": "cam2", "template": "strict_minio_alarm_pipeline" },
    { "name": "cam3", "template": "strict_minio_alarm_pipeline" },
    { "name": "cam4", "template": "strict_minio_alarm_pipeline" },
    { "name": "cam5", "template": "strict_minio_alarm_pipeline" }
  ]
}

参考