MediaMTX 上云部署指南:从单个 Docker 到多可用区,先拍板三个决策
【免费下载链接】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
周五晚九点,直播并发一涌进来,跑着媒体服务的那台单节点 ECS 直接被打满 CPU,读者端开始大面积卡顿。这类场景的解法,通常是把服务搬上公有云。而把一台媒体服务器搬到公有云上跑媒体流,真正麻烦的不是安装,而是动手前的几个决策。MediaMTX 是一个单进程同时覆盖 SRT、WebRTC、RTSP、RTMP、LL-HLS 的流媒体服务器,支持发布、转发、录制和回放,云部署本身不复杂,但下面这三件事想清楚了,能少走很多弯路。
动手前先拍板的三件事
- 镜像怎么挑:仓库里的 standard.Dockerfile 基于
scratch构建,按TARGETPLATFORM自动选 amd64 / arm64 / armv7 二进制。公有云上 ECS 基本是 x86 或 arm64(倚天、Graviton),这个镜像都覆盖;需要转码能力才看 ffmpeg.Dockerfile,树莓派那版用不上。 - 配置怎么注入:MediaMTX 支持三种方式,混合使用最省心,对比如下。
| 方式 | 适用场景 | 注意点 |
|---|---|---|
| 配置文件 | 完整基线配置 | 路径正则、source 这类复杂字段建议只放文件里 |
| 环境变量 | 少量覆盖 | 命名规则是MTX_前缀加大写字段名,如MTX_API |
| Control API | 运行时改路径/限流 | 改的是内存态,重启后丢失,需配合 API 文档 |
- 端口怎么开:这是云上最容易被忽略的一点。核心监听:RTSP 8554/tcp、RTSPS 8322/tcp、RTP 8000–8007/udp、RTMP 1935/tcp、HLS 8888/tcp、WebRTC 8889/tcp、ICE 8189/udp、SRT 8890/udp、API 9997/tcp、Metrics 9998/tcp。安全组按实际启用的协议最小化放行,UDP 段一定要单独放,漏了 UDP 的症状就是"TCP 握手成功但画面卡死"。
用 Docker Compose 跑通最小部署
先上单节点,K8s 的事后面再说。下面这个版本我认为是能跑通的最短形态:
services: mediamtx: image: mediamtx:latest # WebRTC/SRT/RTSP 大量走 UDP,bridge 网络 NAT 容易把 ICE 搞挂,用 host 网络最稳 network_mode: host environment: # 只把少量开关放环境变量;完整字段清单见仓库 mediamtx.yml - MTX_API=yes # 开 Control API,健康检查和动态路径都靠它 volumes: # 拉流地址、path 这类复杂配置放文件里,环境变量写不干净 - ./mediamtx.yml:/mediamtx.yml restart: always几个字段的理由:network_mode: host是因为媒体 UDP 对 NAT 很敏感,而且省一层端口映射;host 模式下端口直接暴露在主机的 8554/8888/8189 等,安全组照上面的清单放行即可;MTX_API=yes是后面健康检查和运维操作的入口。验证方式很简单:起一个容器,用 ffmpeg 往rtsp://<ECS公网IP>:8554/test推一路,再从 HLS 地址http://<公网IP>:8888/test/index.m3u8读回来,能看就说明链路通了。如果你要上 K8s,思路是 Deployment + headless Service 或 StatefulSet 按 path 固定实例,这一节不展开,直接看后面。
生产加固的三个层次
多副本怎么摆
⚠️ 先泼冷水:MediaMTX 的路径是有状态的,一条 path 只有一个 publisher,挂在某个实例上,所以多副本不是简单的负载均衡。正确的摆法是按 path 切分:每路流固定路由到某个副本(客户端侧按 path 做一致性哈希,或 DNS 分流不同前缀)。K8s 上再加一条topologySpreadConstraints,把副本摊到不同可用区,单 AZ 挂掉时其余副本还能服务各自的路径。
指标和健康检查怎么接
mediamtx.yml里把metrics: yes、metricsAddress: ":9998"打开,Prometheus 直接抓:9998/metrics。真实存在的指标是paths(活跃路径数)、paths_readers(按路径的读者数)、paths_inbound_bytes/paths_outbound_bytes(出入流量),注意它没有mtx_前缀那种旧指标名。健康检查打 Control API 的:9997/v3/info即可,K8s 里配httpGet探针;日志走logDestinations: [stdout]交给平台采集,比写本地文件省得自己管轮转。
证书和认证怎么挂
三件事就够:一是给对外协议开加密,webrtcEncryption、hlsEncryption(低延迟 HLS 在苹果设备上必须走 HTTPS)、rtspEncryption都设为"optional"或"strict";二是认证别用默认空密码,简单场景在authInternalUsers里给publish动作绑一个ips白名单,只放行推流机所在网段;三是对接企业身份体系就配authJWTJWKS,客户端把 JWT 当密码传,权限写进mediamtx_permissionsclaim,省掉自己维护账号表。
演进路线和四个最常踩的坑
三步走:
- 验证:单节点跑通推读回路,打开 API 和 Metrics,接上 Prometheus。
- 高可用:两副本起、跨 AZ 打散、协议全量 TLS、按 path 路由固定。
- 弹性:副本按 path 数量扩;拉流型路径开
sourceOnDemand: yes配sourceOnDemandCloseAfter,没读者时自动断上游,省带宽比扩容更划算。
Q/A 部分:
Q:镜像是 scratch 基底、连 shell 都没有,Docker 的 healthcheck 怎么写?A:标准镜像里跑不了curl,所以 Docker 场景要么用 sidecar 容器探测,要么接受靠平台层面监控;K8s 的httpGet探针不依赖容器内命令,是更省事的方案。
Q:端口全开了,浏览器 WebRTC 还是连不上?A:多半是webrtcIPsFromInterfaces默认把 ECS 的私网 IP 发给了客户端。云上必须把公网 IP 或域名填进webrtcAdditionalHosts,这个坑我踩过一次。
Q:多副本下,读者会连到和 publisher 同一个副本吗?A:不会自动发生。同一路流只存在于一个实例上,必须按 path 切分流量,或者用source: redirect让副本间做源重定向。
Q:怎么防止一路热门流吃光整机资源?A:pathDefaults里设maxReaders给单路流限并发,再配合指标里的paths_readers做告警,超了扩副本而不是升配单机。
完整的字段说明和默认值都在 docs/5-references/1-configuration-file.md,遇到坑欢迎提 issue 一起讨论。
【免费下载链接】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),仅供参考