MediaMTX 1.21.3 API 使用详解
基于 MediaMTX v1.21.3 实测:REST API 认证、paths/config/sessions 域端点回显、kick 踢出、Prometheus 指标与 WHEP 信令。
MediaMTX 1.21.3 API 使用详解
目标:系统讲清 MediaMTX v1.21.3 的 REST 控制 API(端口 9997)与 Prometheus 指标 API(端口 9998)——从认证、分页约定到路径管理、配置热更新、会话踢出的全端点实测手册,所有请求与响应 JSON 均为真实环境逐条调用回显(实测日期 2026-10-29)。
一、环境信息
本文所有 API 调用均在以下真实环境实测通过:
- 操作系统:Ubuntu 22.04(x86_64)
- MediaMTX:v1.21.3(API 与正文服务同进程,部署见《MediaMTX 1.21.3 Docker Compose 部署指南》)
- 服务端监听:REST API
:9997(实测日志INF [API] started with listener on :9997 (TCP/HTTP))、metrics:9998 - 客户端:curl 8.x;示例中认证账号为演示账号
admin:q1w2e3r4 - 测试流:RTSP 推入 path
cam(H264+AAC),另有 RTMP pathcam_rtmp、SRT pathcam_srt同时在线
二、前置条件
- 开启 API:配置
api: yes(默认关闭),并准备一个带action: api权限的账号(authInternalUsers配置法见《MediaMTX 1.21.3 配置参数详解》5.3 节); - 客户端工具:curl 即可;需要格式化 JSON 时可接
python3 -m json.tool; - 版本差异提醒:MediaMTX 的 API 路径前缀为
/v3/(v3 是当前代次)。网上旧资料提到的/v3/streams/*、POST /v3/paths/kick/{name}在 v1.21.3 实测均返回404 page not found——流状态已并入 paths 资源,踢连接改到 conns/sessions 资源上(本文 5.5 实测),请以本文实测端点矩阵为准。
三、API 总览
| 域 | 资源 | 方法 | 用途 |
|---|---|---|---|
| 路径 | /v3/paths/list、/v3/paths/get/{name} | GET | 查看路径与流状态(含读者、轨道、字节计数) |
| RTSP 连接/会话 | /v3/rtspconns/list、/v3/rtspsessions/list | GET | RTSP 连接与会话(两级模型) |
| RTMP/SRT 连接 | /v3/rtmpconns/list、/v3/srtconns/list | GET | RTMP/SRT 连接(单级模型) |
| HLS 会话 | /v3/hlssessions/list | GET | 在看的 HLS 播放会话 |
| WebRTC 会话 | /v3/webrtcsessions/list | GET | WebRTC 会话 |
| 连接/会话踢出 | POST /v3/{rtspconns,rtspsessions,rtmpconns,srtconns,hlssessions,webrtcsessions}/kick/{id} | POST | 断开指定连接/会话 |
| 全局配置 | /v3/config/global/get、/v3/config/global/patch | GET/PATCH | 121 个全局参数读取与热更新 |
| 路径默认配置 | /v3/config/pathdefaults/get | GET | 92 个 pathDefaults 参数 |
| 路径配置 | /v3/config/paths/{add,patch,remove}/{name} | POST/PATCH/DELETE | 运行时增删改路径 |
| 指标 | :9998/metrics | GET | Prometheus 文本格式 |
约定:API 仅支持 HTTP(:9997 明文,生产前置反代加 TLS);认证用 HTTP Basic;响应为 JSON(错误响应实测形态如 {"status":"error","error":"authentication error"});列表类响应统一 {itemCount,pageCount,items} 三键分页结构。请求体超限/非法参数返回 400,未认证返回 401,未知端点返回 404(均实测)。
四、认证与首次调用
首次调用先验证认证边界——匿名请求(实测源 IP 不在放行网段时):
curl -s http://127.0.0.1:9997/v3/paths/list
实测回显:
{"status":"error","error":"authentication error"}
带 Basic 认证重试:
curl -s -u admin:q1w2e3r4 http://127.0.0.1:9997/v3/paths/list | head -c 120
实测回显(节选):
{"itemCount":1,"pageCount":1,"items":[{"name":"cam","confName":"cam","ready":true,"online":true}]}
(输出节选(实测首尾):完整 items 结构见 5.1)
⚠️ 排障实录:v1.21 内置用户默认仅对
localhost放行;经端口映射/跨机访问时服务端看到的源 IP 是网关地址(如 10.89.61.1)而非 127.0.0.1,匿名请求即 401。给any用户加ips: ['10.0.0.0/8', '172.16.0.0/12']内网段或使用具权限账号即可。
五、各 API 域详解
5.1 路径域:查看流状态
GET /v3/paths/list:列出全部路径。实测回显(输出节选(实测首尾):完整 JSON 含更多计数字段,此处截取关键字段并格式化):
{"itemCount":1,"pageCount":1,"items":[{"name":"cam","confName":"cam","ready":true,
"readyTime":"2026-10-29T12:48:24.35468968Z","available":true,
"availableTime":"2026-10-29T12:48:24.35468968Z","online":true,
"onlineTime":"2026-10-29T12:48:24.35469233Z",
"source":{"type":"rtspSession","id":"247560ac-a091-4d04-8f34-1afd9f2837d5"},
"tracks":["H264","MPEG-4 Audio"],
"tracks2":[{"codec":"H264","codecProps":{"width":640,"height":480,"profile":"High","level":"3"}},
{"codec":"MPEG-4 Audio","codecProps":{"sampleRate":44100,"channelCount":1}}],
"readers":[],"inboundBytes":0,"outboundBytes":0,"inboundFramesInError":0,
"bytesReceived":4811342,"bytesSent":0}]}
字段解读:ready/available/online 三态都为 true 表示流可播;source.type 是来源类型(rtspSession/rtmpConn/srtConn/hlsMuxer/webRTCSession/redirect/staticSource 等);tracks 是编码列表,tracks2 带分辨率/采样率等属性;bytesReceived 为累计入流量。
GET /v3/paths/get/cam:取单条路径,字段同上。用 python 提取关键值实测:
curl -s -u admin:q1w2e3r4 http://127.0.0.1:9997/v3/paths/get/cam | python3 -c "
import json,sys
d=json.load(sys.stdin)
print('name:', d['name'], '| ready:', d['ready'], '| tracks:', d['tracks'], '| bytesReceived:', d.get('bytesReceived'))"
实测回显:
name: cam | ready: True | tracks: ['H264', 'MPEG-4 Audio'] | bytesReceived: 4811342
5.2 配置域:读取与热更新
GET /v3/config/global/get:121 个全局参数当前生效值(实测键数 121)。实测落盘统计:
curl -s -u admin:q1w2e3r4 http://127.0.0.1:9997/v3/config/global/get -o g.json
python3 -c "import json; print('global 参数键总数:', len(json.load(open('g.json'))))"
实测回显:
global 参数键总数: 121
⚠️ 敏感值脱敏:实测回读时
authInternalUsers中 admin 的密码字段被服务端替换为"<redacted>"——API 不会回吐敏感明文,这也是检查配置是否含敏感值的手段。
PATCH /v3/config/global/patch:热更新(只传要改的键,立即生效,不重启进程)。实测把日志级别切到 debug:
curl -s -u admin:q1w2e3r4 -X PATCH http://127.0.0.1:9997/v3/config/global/patch \
-H 'Content-Type: application/json' -d '{"logLevel":"debug"}'
curl -s -u admin:q1w2e3r4 http://127.0.0.1:9997/v3/config/global/get | grep -o '"logLevel":"[a-z]*"'
实测回显:
{"status":"ok"}
"logLevel":"debug"
GET /v3/config/pathdefaults/get:92 个 pathDefaults 键(实测键数 92),首 8 键实测回显:
{"name": "", "source": "publisher", "sourceFingerprint": "", "sourceOnDemand": false,
"sourceOnDemandStartTimeout": "10s", "sourceOnDemandCloseAfter": "10s", "maxReaders": 0, "srtReadPassphrase": ""}
5.3 路径配置域:运行时增删路径
POST /v3/config/paths/add/{name}:动态添加路径(body 可空 = 用 pathDefaults)。实测先加路径再推流:
curl -s -u admin:q1w2e3r4 -X POST http://127.0.0.1:9997/v3/config/paths/add/cam_rtmp \
-H 'Content-Type: application/json' -d '{}'
实测回显:
{"status":"ok"}
随后 RTMP 推流到 cam_rtmp 成功(服务端日志实测回显:INF [path cam_rtmp] stream is available and online, 2 tracks (H264, MPEG-4 Audio))。此 API 解决了 v1.21「未定义路径拒绝推流」的运维痛点——路径可由运维平台运行时创建,不必改配置重启。PATCH /v3/config/paths/patch/{name} 与 DELETE /v3/config/paths/remove/{name} 同理操作已存在路径。
5.4 会话域:连接与会话查询
RTSP 是两级模型(conn 连接 + session 会话),RTMP/SRT 是单级 conn,HLS/WebRTC 是 session。实测各资源列表状态码:
for ep in rtspconns/list rtspsessions/list rtmpconns/list srtconns/list hlssessions/list webrtcsessions/list; do
printf '%-22s ' "$ep"
curl -s -o /dev/null -w '%{http_code}\n' -u admin:q1w2e3r4 "http://127.0.0.1:9997/v3/$ep"
done
实测回显:
rtspconns/list 200
rtspsessions/list 200
rtmpconns/list 200
srtconns/list 200
hlssessions/list 200
webrtcsessions/list 200
GET /v3/rtspsessions/list 实测回显(输出节选(实测首尾):推流会话,完整 JSON 含更多 RTP 计数字段):
{"itemCount":1,"pageCount":1,"items":[{"id":"247560ac-a091-4d04-8f34-1afd9f2837d5",
"created":"2026-10-29T12:48:24.350113002Z","remoteAddr":"10.89.61.1:42828","state":"publish",
"path":"cam","query":"","user":"","expiresAt":null,"userAgent":"Lavf60.16.100","transport":"TCP",
"profile":"AVP","conns":["9b205f4e-7aa8-4e83-8abb-3e796a47d7fa"],"inboundBytes":4919664,"inboundRTPPackets":5725,...}]}
字段解读:state 为 publish/read;userAgent 直接暴露客户端(Lavf60.16.100 即 FFmpeg 6.0.x 的 libavformat 版本串);inboundRTPPackets 等计数可用于流量审计。
GET /v3/webrtcsessions/list 在无观看者时实测回显:
{"itemCount":0,"pageCount":0,"items":[]}
5.5 踢出域:断开指定连接
v1.21.3 的踢出端点是各资源下的 POST /v3/<资源名>/kick/{id}(旧文档的 POST /v3/paths/kick/{name} 与 DELETE /v3/rtmpconns/{id} 实测均 404)。实测踢掉 RTMP 推流连接:
RMID=$(curl -s -u admin:q1w2e3r4 http://127.0.0.1:9997/v3/rtmpconns/list \
| python3 -c "import json,sys; print(json.load(sys.stdin)['items'][0]['id'])")
echo "rtmp conn id=$RMID"
curl -s -o /dev/null -w 'POST /v3/rtmpconns/kick/{id}: %{http_code}\n' \
-u admin:q1w2e3r4 -X POST "http://127.0.0.1:9997/v3/rtmpconns/kick/$RMID"
实测回显:
rtmp conn id=6ab6c013-c627-42dc-aa16-285181304435
POST /v3/rtmpconns/kick/{id}: 200
服务端日志确认断开(实测回显):
2026/10/29 12:51:55 INF [RTMP] [conn 10.89.61.1:46242] closed: terminated
closed: terminated 即 API 踢出的标志字样。RTSP session、SRT conn、HLS/WebRTC session 的 kick 同构。
5.6 指标域:Prometheus(9998 端口)
metrics 是独立 HTTP 端口(metrics: yes 后 :9998),认证同 API(需 action: metrics 权限)。实测:
curl -s -u admin:q1w2e3r4 http://127.0.0.1:9998/metrics | head -6
实测回显:
# Paths
paths{name="cam",state="ready"} 1
paths_readers{name="cam",readerType="",state="ready"} 0
paths_inbound_bytes{name="cam",state="ready"} 5773613
paths_outbound_bytes{name="cam",state="ready"} 3039552
paths_inbound_frames_in_error{name="cam",state="ready"} 0
Prometheus 抓取配置 metrics_path: '/metrics' 加 Basic auth 即可接入监控栈。
5.7 WebRTC 信令(HTTP API 形态)
WHEP 播放信令也是 HTTP API:POST /{path}/whep 提交 SDP offer(Content-Type: application/sdp)换取 answer。实测:
curl -si -X POST -H 'Content-Type: application/sdp' --data-binary @offer.sdp \
http://127.0.0.1:8889/cam/whep | head -8
实测回显(响应头部分):
HTTP/1.1 201 Created
Accept-Patch: application/trickle-ice-sdpfrag
Content-Type: application/sdp
Etag: *
Id: f624a295-06b6-4f5e-bbdc-10290a9b338a
Location: /cam/whep/69e4a6a9-e93d-4c78-a248-6f1519965cab
Server: mediamtx
201 + Location 指向会话资源;answer SDP 含 a=fingerprint:sha-256 与 a=setup:active(完整 992 字节 answer 实测)。推流方向对应 POST /{path}/whip。该信令可直接集成到自研播放器做信令层。
六、分页/过滤/排序通用约定
实测归纳(v1.21.3):
- 分页:列表类响应固定三键
{itemCount, pageCount, items};实测 1 条数据返回{"itemCount":1,"pageCount":1,"items":[<路径对象>]},0 条返回{"itemCount":0,"pageCount":0,"items":[]}; - 过滤:路径类支持单条取回(
/v3/paths/get/{name}),列表本身无查询参数过滤; - 排序:
items按创建时间升序(实测多路径场景),无排序参数; - 错误结构:统一
{"status":"error","error":"<原因>"};HTTP 状态码:401 未认证、404 端点或资源不存在、400 请求体非法; - 幂等性:GET 幂等;PATCH 只改传入键;POST add 重复添加同名路径实测返回错误而非覆盖,先 remove 再 add。
七、常见问题
Q1:/v3/streams/list、POST /v3/paths/kick/{name} 为什么 404?
这两类端点是旧版本形态。v1.21.3 实测 404:流状态看 /v3/paths/get/{name}(source/readers 字段齐全),踢连接用 POST /v3/{rtspconns|rtspsessions|rtmpconns|srtconns|hlssessions|webrtcsessions}/kick/{id}(实测 200 生效,见 5.5)。
Q2:匿名调用报 authentication error?
见第四章:给账号配 action: api 权限并 -u 携带;或把来源网段加入 any 用户 ips。
Q3:PATCH 返回 ok 但行为没变?
先 GET /v3/config/global/get 确认键名与新值已生效(实测 logLevel patch 后立即回读为 debug);部分协议参数(如监听地址)热改需重启进程才重建监听,属预期。
Q4:密码能不能从 API 读回来?
不能。实测敏感字段回读为 <redacted>,这是服务端脱敏行为。
八、参考链接
- 官方 Control API 文档:https://github.com/bluenviron/mediamtx/wiki/Control-API
- 官方 OpenAPI 描述(随仓库分发 openapi.yaml)
- 本系列:《MediaMTX 1.21.3 介绍与选型指南》、《MediaMTX 1.21.3 Docker Compose 部署指南》、《MediaMTX 1.21.3 配置参数详解》