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
MediaMTX 是一个单二进制的实时流媒体服务器,支持 RTSP、RTMP、HLS、WebRTC、SRT 等协议,能把摄像头或推流端的音视频流转给多路协议的下游客户端,并支持录制与回放。本文带你从一条docker run命令跑通 MediaMTX 部署的第一个可用实例,再走到带健康检查、持久化存储和生产暴露方式的完整部署。
一、场景与部署方式选型
典型场景:安防摄像头用 RTSP 出流,网页端要用 WebRTC/HLS 播放,业务系统要拉 RTMP,还要把录像留存下来。没有 MediaMTX 时,你要在 RTSP 转 HLS、RTSP 转 WebRTC 之间写一堆胶水服务。MediaMTX 把这些协议收敛到同一个进程里,一条路径(path)进、多协议出。
环境要求:
- Linux 服务器(Docker/K8s 部署不挑发行版),或任何能跑 Docker 的机器
- 端口:RTSP 8554/tcp,RTMP 1935/tcp,HLS 8888/tcp,WebRTC 8889/tcp + 8189/udp,SRT 8890/udp,Control API 9997/tcp(默认关闭),Metrics 9998/tcp(默认关闭)
- 无数据库、无外部依赖,配置文件为单个
mediamtx.yml
部署方式对比:
| 方式 | 难度 | 适用规模 | 运维成本 | 说明 |
|---|---|---|---|---|
| 独立二进制 | 低 | 开发/试用 | 低 | 下载即跑,无隔离 |
| Docker 容器 | 低 | 单机生产 | 低 | 官方推荐的生产方式,配置热更新 |
| Kubernetes | 中 | 多业务共享集群 | 中 | 适合要编排、监控、自动恢复的团队 |
本文推荐Docker 起步,第二节用它跑通实例,第五节直接给 Kubernetes 生产模板。
二、三步快速启动
第 1 步:启动容器。:1标签对应最新 1.x 版本;MTX_RTSPTRANSPORTS=tcp关闭 RTSP 的 UDP 传输,避免 Docker 网络改写 UDP 源地址导致播放失败,这是官方安装文档给出的标准做法。
docker run -d --name mediamtx \ --restart unless-stopped \ -e MTX_RTSPTRANSPORTS=tcp \ -e MTX_WEBRTCADDITIONALHOSTS=192.168.1.10 \ -p 8554:8554 \ -p 1935:1935 \ -p 8888:8888 \ -p 8889:8889 -p 8189:8189/udp \ -p 8890:8890/udp \ -p 9997:9997 \ bluenviron/mediamtx:1其中MTX_WEBRTCADDITIONALHOSTS填客户端实际能访问到的 IP,容器内网 IP 对外不可达时 WebRTC 握手会失败。
第 2 步:推一路测试流。用 ffmpeg 生成测试画面推到 RTMP 的live路径。
ffmpeg -re -f lavfi -i testsrc=duration=120:size=640x360:rate=30 \ -c:v libx264 -preset veryfast -f flv rtmp://127.0.0.1:1935/live第 3 步:验证多协议输出。同一路流可以直接拉 HLS 播放列表,确认转发生效。
curl -s http://127.0.0.1:8888/live/index.m3u8 | head能看到#EXTM3U内容即部署成功。完整安装与镜像变体(含 FFmpeg、树莓派摄像头的1-ffmpeg、1-rpi)见 官方安装文档。
三、核心配置精讲
MediaMTX 的所有配置集中在mediamtx.yml,支持环境变量覆盖(前缀MTX_,如MTX_API=true),且文件保存后热加载生效,不用重启进程。以下是生产上最常动的 8 项:
| 配置项 | 默认值 | 何时改 |
|---|---|---|
logLevel | info | 排查协议问题时改debug |
api/apiAddress | false/:9997 | 需要运维接口、健康检查时开启 |
metrics/metricsAddress | false/:9998 | 接入 Prometheus 时开启 |
rtspTransports | [udp, multicast, tcp] | 在 NAT、负载均衡或容器后改为[tcp] |
hlsVariant | lowLatency | 追求最大兼容性或 Apple 设备未走 HTTPS 时改mpegts |
webrtcAdditionalHosts | 空 | 客户端经公网/内网 IP 访问时填入该地址 |
pathDefaults.source | publisher | 改成rtsp://...可直接拉摄像头 |
record/recordDeleteAfter | false/1d | 开启录制及录像保留时长 |
最小生产配置文件(只保留用到的字段,完整参考见 配置项全集):
logLevel: info api: true apiAddress: :9997 metrics: true metricsAddress: :9998 rtspTransports: [tcp] # 容器/负载均衡后统一走 TCP webrtcAdditionalHosts: [192.168.1.10] # 客户端可达的 IP authInternalUsers: - user: any pass: ips: [] permissions: - action: publish - action: read - user: any pass: ips: ["10.0.0.0/8"] # 默认只允许 127.0.0.1,运维段需显式放开 permissions: - action: api - action: metrics pathDefaults: source: publisher record: true recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f recordFormat: fmp4 recordDeleteAfter: 7d要点:
- 默认配置里 API/Metrics 只对
127.0.0.1免密,第二条authInternalUsers是给运维网段放行的,ips按你的监控源地址修改。 recordPath必须指向可写目录,Docker 里要挂载出来,否则录像只写在容器层。paths下可用~前缀写正则匹配多路流,如~^cam,未匹配的走all_others。
挂载配置运行(配置文件以只读方式挂到/config,录像目录独立挂载):
docker run -d --name mediamtx \ --restart unless-stopped \ -p 8554:8554 -p 1935:1935 -p 8888:8888 \ -p 8889:8889 -p 8189:8189/udp -p 8890:8890/udp \ -p 9997:9997 -p 9998:9998 \ -v "$PWD/mediamtx.yml:/config/mediamtx.yml:ro" \ -v "$PWD/recordings:/recordings" \ -w /config \ bluenviron/mediamtx:1 ./mediamtx.yml四、Kubernetes 生产级部署
三个前提:多副本时同一路径的发布者和读者只在同一实例内共享,跨 Pod 不通,所以副本数不是越高越好,横向扩容靠按路径分片;录像用 PVC 持久化;API 端口只用于探针和运维,不给公网开。
ConfigMap(配置内容同第三节,此处省略注释):
apiVersion: v1 kind: ConfigMap metadata: name: mediamtx-config namespace: mediamtx data: mediamtx.yml: | logLevel: info api: true apiAddress: :9997 metrics: true metricsAddress: :9998 rtspTransports: [tcp] webrtcAdditionalHosts: [203.0.113.10] pathDefaults: source: publisher record: true recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f recordFormat: fmp4 recordDeleteAfter: 7dDeployment:
apiVersion: apps/v1 kind: Deployment metadata: name: mediamtx namespace: mediamtx spec: replicas: 1 # 路径不跨实例共享,先跑单副本 selector: matchLabels: app: mediamtx template: metadata: labels: app: mediamtx spec: containers: - name: mediamtx image: bluenviron/mediamtx:1 args: ["/mediamtx.yml"] ports: - {containerPort: 8554, name: rtsp} - {containerPort: 1935, name: rtmp} - {containerPort: 8888, name: hls} - {containerPort: 8889, name: webrtc} - {containerPort: 8189, name: webrtc-ice, protocol: UDP} - {containerPort: 8890, name: srt, protocol: UDP} - {containerPort: 9997, name: api} - {containerPort: 9998, name: metrics} volumeMounts: - {name: config, mountPath: /mediamtx.yml, subPath: mediamtx.yml} - {name: recordings, mountPath: /recordings} resources: requests: {cpu: 250m, memory: 256Mi} limits: {cpu: "2", memory: 1Gi} livenessProbe: httpGet: {path: /v3/info, port: api} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: {path: /v3/info, port: api} initialDelaySeconds: 5 periodSeconds: 5 volumes: - name: config configMap: name: mediamtx-config - name: recordings persistentVolumeClaim: claimName: mediamtx-recordings-pvc关键字段说明:
- 探针:
/v3/info是 Control API 的存活端点,探针从 Pod 本地回环发起,命中"localhost 免密"规则,不需要为探针开放认证。 - resources:MediaMTX 转发带宽大、拷贝少,CPU 上限给到 2 核、内存 1Gi 对几十路 1080p 转发足够,可按实际负载调。
- UDP 端口:SRT 与 WebRTC ICE 都是 UDP,
protocol: UDP不能漏,漏了跨网段播放必挂。 - replicas: 1:需要扩容时,为不同业务路径建多个 Deployment 分片,而不是拉高副本数。
Service 与 PVC:
apiVersion: v1 kind: Service metadata: name: mediamtx namespace: mediamtx spec: type: LoadBalancer selector: app: mediamtx ports: - {name: rtsp, port: 8554, targetPort: 8554} - {name: rtmp, port: 1935, targetPort: 1935} - {name: hls, port: 8888, targetPort: 8888} - {name: webrtc, port: 8889, targetPort: 8889} - {name: webrtc-ice, port: 8189, targetPort: 8189, protocol: UDP} - {name: srt, port: 8890, targetPort: 8890, protocol: UDP} - {name: api, port: 9997, targetPort: 9997} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mediamtx-recordings-pvc namespace: mediamtx spec: accessModes: [ReadWriteOnce] resources: requests: storage: 50Gi单副本 + ReadWriteOnce 即可;若后续用分片架构,每个 Deployment 配独立 PVC。应用与检查状态:
kubectl create namespace mediamtx kubectl apply -f configmap.yaml -f pvc.yaml -f deployment.yaml -f service.yaml kubectl get pods,svc -n mediamtx五、运维工具箱
监控:Metrics 端点输出 Prometheus 格式,连接数、读/写者数、协议分布都有;API 可列出当前所有路径与路径详情。
curl -s http://10.0.0.5:9997/v3/paths/list # 当前所有路径 curl -s http://10.0.0.5:9998/metrics | head -20 # Prometheus 指标日志:
kubectl logs -f deployment/mediamtx -n mediamtx kubectl logs deployment/mediamtx -n mediamtx --since=1h | grep -i "warn\|error"备份:配置就一个文件,录像在 PVC 上,备份成本很低。
kubectl get cm mediamtx-config -n mediamtx -o yaml > mediamtx-config-backup.yml # 录像文件在 PVC 上,随底层存储快照一起备份即可升级与回滚:生产建议把镜像 pin 到具体版本号(如1.14.x),:1是 1.x 最新,适合测试。
kubectl set image deployment/mediamtx mediamtx=bluenviron/mediamtx:1.14.0 -n mediamtx kubectl rollout status deployment/mediamtx -n mediamtx kubectl rollout undo deployment/mediamtx -n mediamtx # 出问题立即回滚六、避坑清单
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| WebRTC 握手失败,浏览器黑屏 | 客户端拿到的是容器内网 IP,无法回连 | 设置webrtcAdditionalHosts为公网/可达地址,或配 ICE/STUN |
| RTSP 播放时断或完全不通(Docker 内) | Docker 网络改写了 UDP 包源地址和端口 | MTX_RTSPTRANSPORTS=tcp,或--network=host |
| 从外部访问 9997/9998 返回 401 | 默认仅127.0.0.1免密 | authInternalUsers中给运维网段加api/metrics权限 |
| HLS 在部分设备/播放库打不开 | 默认hlsVariant: lowLatency,Apple 设备要求 HTTPS | 改mpegts,或开启hlsEncryption走 HTTPS |
| 磁盘被录像写满 | recordDeleteAfter默认只保留 1d,或挂载漏了导致文件进容器层 | 显式设置recordPath+recordDeleteAfter,目录务必持久化 |
| 多副本时客户端只能看到部分流 | 路径的发布/读取不跨实例 | 单副本运行,或按路径分片建多个 Deployment |
七、最佳实践
- 生产环境 pin 镜像版本号,升级走
rollout,保留回滚路径。 - RTSP 一律保留
tcp传输,UDP 只在内网可信环境开启。 authInternalUsers的ips白名单按运维/监控网段最小化配置。- 开启
record前确认recordPath已持久化,并用recordDeleteAfter控制保留期。 - 用 Control API 的
/v3/info做探针,Metrics 接 Prometheus 做容量告警。
下一步建议:先按第二节在测试机跑通三路协议(RTSP 推、HLS 拉、API 查),再套第四节模板上集群,配合 录制与回放文档 验证录像链路。
【免费下载链接】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),仅供参考