MediaMTX 云部署实战:从 Docker 单容器到 Kubernetes 的流媒体服务器搭建
【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx
MediaMTX 是一个零依赖的流媒体服务器,一个二进制文件就内置了 RTSP、RTMP、HLS、WebRTC、SRT 五种协议的接入和分发。把它放到公有云上,绕不开两个问题:UDP 端口很容易被 NAT 和安全组拦掉,桥接网络又会让 WebRTC 客户端拿不到正确地址。先说结论:上云之后把传输尽量收敛到 TCP、显式声明公网 IP,这两件事做完,绝大多数部署问题就解决了。
先跑起来:MediaMTX Docker 一行命令
官方镜像bluenviron/mediamtx:1基于 scratch 构建(见 docker/standard.Dockerfile),没有 shell,镜像体积只有几 MB。一条命令起服务,TCP/UDP 端口按官方安装文档列全:
docker run --rm -d \ -e MTX_WEBRTCADDITIONALHOSTS=<你的公网IP> \ -p 8554:8554 -p 1935:1935 \ -p 8888:8888 -p 8889:8889 \ -p 8892:8892 -p 8892:8892/udp -p 8893:8893/udp \ -p 8890:8890/udp -p 8189:8189/udp \ bluenviron/mediamtx:1常用端口速查(默认值来自 mediamtx.yml):
| 协议 | 端口 | 说明 |
|---|---|---|
| RTSP | 8554 | 默认开启 |
| RTMP | 1935 | 默认开启 |
| HLS | 8888 | 播放列表与分片 |
| WebRTC | 8889 / 8189(udp) | 信令走 HTTP,媒体走 UDP |
| SRT | 8890(udp) | 需安全组放行 UDP |
| MoQ | 8892 / 8893(udp) | QUIC/WebTransport |
验证标准很简单:浏览器访问http://<公网IP>:8888/,能看到路径列表页面就算起来了;拉流测试用ffplay rtsp://<公网IP>:8554/<路径名>能看到画面即可。
配置怎么调:环境变量优先于配置文件
MediaMTX 支持用MTX_前缀的环境变量覆盖配置项,比挂载配置文件更轻。云上常用的几个:
-e MTX_WEBRTCADDITIONALHOSTS=1.2.3.4 -e MTX_RTSPTRANSPORTS=tcp -e MTX_HLSVARIANT=lowLatency三个必须理解的参数:
1. WebRTC 公网地址。webrtcAdditionalHosts告诉客户端"该往哪个 IP 回媒体流"。云主机上它拿到的是内网 IP,客户端自然连不回来,把公网 IP 填进去即可,多 IP 可写多个。
2. RTSP 强制 TCP。Docker 的 NAT 会改写 UDP 报文里的源地址端口,导致 RTSP over UDP 失败。非 host 网络模式下加MTX_RTSPTRANSPORTS=tcp一刀切掉问题。
3. 低延迟 HLS 怎么配。hlsVariant默认就是lowLatency,hlsPartDuration: 200ms、hlsSegmentDuration: 1s的组合能压到秒级以下;如果目标设备兼容性优先,改成mpegts更稳。注意 LL-HLS 在苹果设备上要求 HTTPS,公网播放记得配证书。
带宽兜底两个参数:pathDefaults.maxReaders限制单路流的并发读者数(0 为不限),sourceOnDemand: true则让拉流源"有人看才拉、没人看 10 秒后断开"(sourceOnDemandCloseAfter可调),按量计费的网络带宽能省一大截。
别急着上 K8s:Deployment 怎么写
单机能稳定跑之前,不建议直接上 Kubernetes。真到了需要多副本、自动恢复的阶段,记住三条:
--network=host在 K8s 里不可用,所以"全 TCP + 显式声明 UDP 端口"是唯一可靠路径;- 把
mediamtx.yml放进 ConfigMap 挂载使用,MediaMTX 支持配置热加载,改 ConfigMap 不用重启 Pod; - 录像文件用 PVC 挂出去,别写在容器临时层里。
spec: containers: - name: mediamtx image: bluenviron/mediamtx:1 args: ["/mediamtx", "/config/mediamtx.yml"] ports: - {containerPort: 8554, protocol: TCP} - {containerPort: 1935, protocol: TCP} - {containerPort: 8888, protocol: TCP} - {containerPort: 8889, protocol: TCP} - {containerPort: 8189, protocol: UDP} volumeMounts: - {name: config, mountPath: /config} - {name: rec, mountPath: /recordings} env: - name: MTX_RTSPTRANSPORTS value: "tcp" - name: MTX_WEBRTCADDITIONALHOSTS value: "1.2.3.4"扩缩容不用等:CPU 到 70% 触发 HPA 加副本,MediaMTX 是单进程、按流数吃内存的,副本数按"单实例可承载的并发流数"来估,而不是拍脑袋。
生产环境三件事
健康检查走 Control API。api: true后,9997 端口提供 HTTP 接口,GET /v3/paths返回 200 即代表服务正常。注意镜像里没装 curl,容器内探针用 TCP 探测 9997 端口,或者用带 curl 的 sidecar。
监控指标接 Prometheus。metrics: true后 9998 端口暴露 Prometheus 格式指标,sources、readers计数加收发字节数是告警三板斧。
日志与录像要设边界。容器环境日志只走 stdout 最省事,文件落盘的话交给宿主机的 logrotate(官方文档给了现成配置,见 docs/2-features/18-logging.md)。录像默认只保留一天(recordDeleteAfter: 1d),云盘容量按这个值反推。
⚠️ 最后强调一条:默认配置里authInternalUsers是"任何人可发布和读取,仅 API/Metrics 限本地",直接暴露到公网等于裸奔。上线前至少把ips字段收紧成办公网段或 CDN 出口 IP。
踩坑记录,全是真实代价
- WebRTC 连不上,日志毫无报错:99% 是
webrtcAdditionalHosts配的是内网 IP。先查这条,再考虑 STUN/TURN。 - RTSP over UDP 时通时断:Docker NAT 改写了五元组,加
MTX_RTSPTRANSPORTS=tcp解决;坚持要 UDP 就上 host 网络,但那样又回不到 K8s 的平滑路径,自己权衡。 - healthcheck 里写
curl永远失败:scratch 镜像里没有 curl,别再贴模板配置了。 - LL-HLS 在 Safari 黑屏:苹果设备要求 HTTPS 的 LL-HLS,
hlsEncryption打开并配好证书。
写在最后
MediaMTX 上云不复杂,复杂的是把网络参数想清楚。下一步建议就用本文的 Docker 命令在你自己的云主机上把 RTSP + HLS 两条链路各跑通一次,再对照"生产环境三件事"逐项加,比直接抄一套 K8s 清单快得多。
【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考