Featured image of post 流媒体与 WebRTC 实时视频:ZLMediaKit / MediaMTX / go2rtc / webrtc-streamer 选型与部署

流媒体与 WebRTC 实时视频:ZLMediaKit / MediaMTX / go2rtc / webrtc-streamer 选型与部署

ZLMediaKit 流媒体服务器、MediaMTX、go2rtc 媒体代理、webrtc-streamer + coturn STUN/TURN 部署、推拉流、WebRTC 浏览器播放

安防、直播、视频会议这些"实时音视频"场景,传统方案是 RTSP 摄像头 + 专有协议 + 客户端 SDK,部署和对接成本都很高。WebRTC 让浏览器"原生支持"实时音视频,但 RTSP 摄像头、监控厂商 NVR 不会自己讲 WebRTC——需要在中间架一座桥:流媒体服务器(ZLMediaKit / MediaMTX)、媒体代理网关(go2rtc)、WebRTC 网关(webrtc-streamer)。这篇文章把"摄像头推到 Web 浏览器"这条链路上常用的几款开源工具讲清楚。

阅读对象:要在 Web 端展示 RTSP/海康/大华摄像头画面的开发者、做直播点播的流媒体工程师
覆盖范围:ZLMediaKit 全协议流媒体服务器、MediaMTX、go2rtc 媒体代理、webrtc-streamer + coturn 部署、推拉流命令、浏览器播放

一、链路与角色

一条完整的"RTSP 摄像头 → 浏览器"链路涉及多个角色:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[RTSP 摄像头/NVR]
       │ (RTSP/RTMP/ONVIF)
[流媒体服务器 ZLMediaKit / MediaMTX]   ← 转协议、加水印、录像
       │ (RTMP/HLS/FLV/WebRTC)
[WebRTC 网关 webrtc-streamer]         ← 浏览器可消费的 WebRTC 流
[浏览器 <video> 播放]

关键协议

  • RTSP(Real Time Streaming Protocol):监控摄像头、NVR 的"母语",TCP/UDP 都有
  • RTMP(Real-Time Messaging Protocol):直播"老炮",Adobe 推的,基于 TCP
  • HLS(HTTP Live Streaming):苹果推的,基于 HTTP 切片,延迟 5-30s
  • FLV:B 站流过来的,HTTP 渐进式下载
  • WebRTC:浏览器原生,延迟 < 1s
  • SRT:安全可靠传输,UDP 上的"准 TCP"

二、ZLMediaKit:全能流媒体服务器

ZLMediaKit 是国内开源的"协议转换器"——一个进程能同时讲 RTSP/RTMP/HLS/FLV/WebRTC/SRT,几乎所有"摄像头转 Web 播放"的方案都用它做中转

2.1 编译安装(Linux)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 克隆
git clone https://github.com/ZLMediaKit/ZLMediaKit.git
cd ZLMediaKit
git submodule update --init

# 编译依赖
apt install build-essential cmake libssl-dev

# WebRTC 还要编译 libsrtp
git clone https://github.com/cisco/libsrtp.git
cd libsrtp
./configure --enable-openssl
make -j4 && make install
cd ..

# 编译 ZLMediaKit
mkdir build && cd build
cmake -DENABLE_WEBRTC=on ../
cmake --build . --target MediaServer

# 启动
cd release/linux/Debug
./MediaServer -d &   # 守护进程模式

2.2 端口清单

名称端口协议用途
HTTP80, 443TCPWeb 服务、API
RTMP1935TCP推流
RTP_PROXY10000TCP/UDPRTSP 推流
RTC (WebRTC)8000TCP/UDPWebRTC 推拉流
SRT9000UDPSRT 推流
RTSP554TCPRTSP 服务

2.3 容器化部署(推荐)

1
docker pull zlmediakit/zlmediakit:master

最常用的启动(带 RTC + 端口映射 + 配置持久化):

1
2
3
4
5
mkdir -p /home/docker/zlmediakit/conf
docker run -d --restart=always --name=zlmediakit \
  --net=host \
  -v /home/docker/zlmediakit/conf:/opt/media/conf \
  zlmediakit/zlmediakit:master

或者显式端口映射:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
docker run -d --restart=always --name=zlmediakit \
  -p 1935:1935 \
  -p 8080:80 \
  -p 8443:443 \
  -p 8554:554 \
  -p 10000:10000 \
  -p 10000:10000/udp \
  -p 8000:8000/udp \
  -p 9000:9000/udp \
  -p 40000-40100:40000-40100/udp \
  -p 40000-40100:40000-40100/tcp \
  -v /home/docker/zlmediakit/conf:/opt/media/conf \
  zlmediakit/zlmediakit:master

2.4 核心配置

config.ini(摘录关键段):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[api]
apiDebug=1
secret={{ZLMediaKit_SECRET}}     # 必须修改默认值

[http]
port=80
allow_ip_range=0.0.0.0/0          # 生产环境建议限制

[rtmp]
port=1935

[rtc]
externIP={{PUBLIC_IP}}            # 必须设置,公网 IP
port=8000

[hook]
enable=0                          # 不鉴权(开发)/ 1 开启 hook
# on_publish=https://your-service/hook/on_publish

[protocol]
enable_mp4=0                      # 关闭 mp4 录制
mp4_save_path=./www

secret 必须改:默认 secret 是公开的,生产环境必须改成 32+ 随机字符串,否则别人能直接调 API 拉你的流。

2.5 推流与拉流

FFmpeg 推流

1
2
3
4
5
6
7
# RTMP 推流
ffmpeg -re -i test.flv -vcodec h264 -acodec aac -f flv \
  rtmp://{{HOST}}:1935/live/test2

# RTSP 推流
ffmpeg -re -i test.mp4 -vcodec h264 -acodec aac -f rtsp \
  rtsp://{{HOST}}:554/live/test

ffplay 拉流

1
2
# RTMP 拉流
ffplay rtmp://{{HOST}}:1935/live/test2 -fflags nobuffer -analyzeduration 1000000

WebRTC 拉流(浏览器):

1
http://{{HOST}}:8080/index/api/webrtc?app=live&stream=test&type=play

2.6 添加 RTSP 摄像头

用 ZLMediaKit 的 addStreamProxy API 把远程 RTSP 摄像头拉过来转协议:

1
2
curl -d "secret={{SECRET}}&vhost=defaultVhost&app=live&stream=test&url=rtsp://{{CAM_USER}}:{{CAM_PASS}}@{{CAM_IP}}:554/Streaming/Channels/101" \
  "http://{{ZLM_HOST}}:8080/index/api/addStreamProxy"

返回:

1
2
3
4
5
6
{
  "code": 0,
  "data": {
    "key": "defaultVhost/live/test"
  }
}

得到多种播放地址

协议地址
FLVhttp://{{ZLM_HOST}}:80/live/test.live.flv
HLShttp://{{ZLM_HOST}}:80/live/test/hls.m3u8
WebRTChttp://{{ZLM_HOST}}:80/index/api/webrtc?app=live&stream=test&type=play

删除代理

1
2
curl -d "secret={{SECRET}}&key=defaultVhost/live/test" \
  "http://{{ZLM_HOST}}:8080/index/api/delStreamProxy"

三、MediaMTX:Go 写的极简流媒体服务器

MediaMTX(原 rtsp-simple-server)是 BluEnviron 出品的"零配置"流媒体服务器,Go 单文件、跨平台、配置项极少,适合"快速搭一个 RTSP/RTMP/HLS/WebRTC 都能讲"的服务

  • 官网:https://github.com/bluenviron/mediamtx
  • 配置文件:mediamtx.yml
  • 启动:./mediamtxdocker run --net=host bluenviron/mediamtx:latest

vs ZLMediaKit:MediaMTX 配置简单、Go 生态友好、集群模式原生;ZLMediaKit 协议支持更全(C++ 实现,定制能力更强)、国内社区活跃、有中文文档。

四、go2rtc:媒体代理网关

go2rtc 解决"RTSP 摄像头接入多套系统"的问题——一次拉流,多协议分发,支持 RTSP/RTMP/HLS/WebRTC/MJPEG/HomeKit/ONVIF。

4.1 部署

1
2
3
4
5
6
7
8
docker run -d \
  --name go2rtc \
  --network host \
  --privileged \
  --restart always \
  -e TZ=Asia/Shanghai \
  -v /home/docker/go2rtc:/config \
  alexxit/go2rtc:1.9.8

访问 http://{{HOST}}:1984/ 看 Web UI。

4.2 添加 RTSP 流

/home/docker/go2rtc/go2rtc.yaml

1
2
3
4
5
6
7
api:
  origin: "*"
streams:
  一楼大厅:
    - rtsp://{{CAM_USER}}:{{CAM_PASS}}@{{CAM_IP}}:554/Streaming/Channels/101
  四楼大厅:
    - rtsp://{{CAM_USER}}:{{CAM_PASS}}@{{CAM_IP_2}}:1554/Streaming/Channels/101

4.3 鉴权(生产环境)

1
2
3
4
api:
  origin: "*"
  username: "admin"
  password: "{{REDACTED}}"

4.4 验证

1
2
3
# WebSocket 方式验证推流
wscat -c "wss://go2rtc.example.com/api/ws?src={{STREAM_ID}}" \
  --header "Authorization: Basic {{BASE64_USER_PASS}}"

go2rtc 优势:用 WebRTC 时延迟能压到 0.4s 左右,远低于 HLS 的 5-30s。比 ZLMediaKit 启动更快,配置更少。

五、webrtc-streamer + coturn:浏览器 WebRTC 网关

webrtc-streamer 是 mpromonet 写的"小 HTTP server + WebRTC 客户端",核心功能是把 RTSP 流通过 WebRTC 推给浏览器

5.1 STUN/TURN 服务器(coturn)

WebRTC 在 NAT 环境下需要 STUN/TURN 中继。coturn 是开源的 TURN/STUN 服务器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mkdir -p /home/docker/coturn
cat << EOF > /home/docker/coturn/my.conf
listening-ip={{INTERNAL_IP}}
listening_port=3478
tls-listening-port=5349
relay-ip={{INTERNAL_IP}}
external-ip={{PUBLIC_IP}}
relay-threads=50
lt-cred-mech
min-port=49152
max-port=65535
user=admin:{{REDACTED}}
cli-password={{REDACTED}}
realm={{PUBLIC_IP}}
verbose
fingerprint
syslog
EOF

docker run -d --restart=always \
  --network=host \
  --name=coturn \
  -v /home/docker/coturn/my.conf:/etc/coturn/my.conf \
  coturn/coturn:latest \
  -c /etc/coturn/my.conf

5.2 webrtc-streamer 部署

1
2
3
4
5
6
7
docker run -d --restart=always \
  --name=webrtc-streamer \
  --net=host \
  mpromonet/webrtc-streamer:v0.8.9 \
  -o -v \
  -S"{{PUBLIC_IP}}:3478" \
  -Tadmin:{{REDACTED}}@"{{PUBLIC_IP}}:3478"

必须加 -o 参数:使用空编解码器(保持帧编码),不转码,否则预览几路 CPU 就 100%。

5.3 公网部署架构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[内网]                              [公网]
RTSP 摄像头 (192.168.1.100:554)
webrtc-streamer (内网 192.168.1.8:8000)
       └──→ 内网穿透 / 端口映射
              8000/tcp → 18000
              3478/udp/tcp → 13478
[公网访问]
浏览器 → http://{{PUBLIC_IP}}:18000/webrtcstreamer.html?video=rtsp://...

5.4 浏览器播放

修改 webrtcconfig.js

1
2
3
4
5
6
new WebRtcStreamer("video1", "http://{{PUBLIC_IP}}:18000");
webRtcServer1.connect(
  "rtsp://{{CAM_USER}}:{{CAM_PASS}}@{{CAM_IP}}:554/Streaming/Channels/501",
  "",  // audioUrl
  "rtptransport=tcp&timeout=60"
);

打开 webrtcstreamer.html,几秒内浏览器就能看到摄像头画面。

5.5 关键 API

API用途
/api/helpAPI 列表
/api/getPeerConnectionList当前活跃的 WebRTC 连接(排障必看
/api/getStreamList正在拉的 RTSP 流
/api/whepWHEP 协议接入(WebRTC-HTTP Egress Protocol)

六、踩坑清单

  1. 必须加 -o 参数——webrtc-streamer 不加 -o 启动,CPU 100% 飙满
  2. H265 不支持——webrtc-streamer 只支持 H264 视频码流,H265 要在摄像头侧或 ZLMediaKit 转码
  3. WebRTC 401 鉴权失败——前端 webrtcconfig.js 的 server URL 配错,或者 backend Authorization 没传对
  4. STUN/TURN 端口未映射——3478 TCP/UDP 都要在公网开放,否则 WebRTC 建联失败
  5. ZLMediaKit secret 没改——默认 secret 是公开的,别人能直接拉你的流
  6. Nginx 反代 WebRTC——必须带 Upgrade / Connection: upgrade,否则 WebSocket 建联失败
  7. RTSP over TCP——内网穿透时 UDP 经常被丢,强制 rtsp_transport=tcp 让 ffplay/webrtc-streamer 用 TCP 拉流

七、2024+ 视角补充

本文写于 2025-01,2025-2026 期间流媒体生态关键演进:

  • ZLMediaKit 持续活跃:2024-2025 累计 100+ commits,WebRTC WHIP/WHEP 标准协议(vs 老的自研协议)、H265/WebCodecs 浏览器原生SRT 推流成熟
  • MediaMTX(原 rtsp-simple-server)1.10+RTSP / RTMP / HLS / WebRTC / SRT / RTSPS 全部支持;Pion WebRTC(Go 实现)性能优化;API v3 替代 v2
  • go2rtc 1.9+FFmpeg 7.0 兼容H265 浏览器播放(基于 WebCodecs)、ONVIF 探测内置
  • webrtc-streamer 0.8.x 维护模式:社区转向 Pion / LiveKit 体系
  • LiveKit 1.8+(2024-2026):云原生 SFU(Go + Rust),K8s 部署友好,WebRTC + SIP 网关——全平台视频会议 / 直播一体化新选择
  • mediasoup 3.x:Node.js SFU 库,低延迟直播 / 互动直播首选
  • Janus 1.3+:老牌 WebRTC Gateway,SIP / RTSP / WebRTC 三栖,2024 仍稳定
  • 云方案:声网 Agora / 腾讯云 TRTC / 阿里云 RTC 2024+ 仍是商业首选

实战建议(2025-2026 视角)

  • RTSP 摄像头 → Web → ZLMediaKit + go2rtc 组合仍是开源首选
  • 互动直播 / 会议LiveKit(云原生 SFU)崛起,vs mediasoup 部署更简单
  • 超低延迟(< 500ms)→ WebRTC + LiveKit / mediasoup
  • H265 + 浏览器 → 必须 WebCodecs(2024+ Chrome / Edge / Safari 支持)
  • 商业 / 大规模 → 声网 / 腾讯 TRTC 仍是最省心选择

八、参考资料

  • ZLMediaKit:https://github.com/ZLMediaKit/ZLMediaKit
  • MediaMTX:https://github.com/bluenviron/mediamtx
  • go2rtc:https://github.com/AlexxIT/go2rtc
  • webrtc-streamer:https://github.com/mpromonet/webrtc-streamer
  • coturn:https://github.com/coturn/coturn
  • WebRTC samples:https://webrtc.github.io/samples/
  • LiveKit:https://livekit.io
  • mediasoup:https://mediasoup.org

下一步

使用 Hugo 构建
主题 StackJimmy 设计