MediaMTX 1.21.3 API 使用详解

基于 MediaMTX v1.21.3 实测:REST API 认证、paths/config/sessions 域端点回显、kick 踢出、Prometheus 指标与 WHEP 信令。

MediaMTXMediaMTXRTSPWebRTC2026/10/29

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 path cam_rtmp、SRT path cam_srt 同时在线

二、前置条件

  1. 开启 API:配置 api: yes(默认关闭),并准备一个带 action: api 权限的账号(authInternalUsers 配置法见《MediaMTX 1.21.3 配置参数详解》5.3 节);
  2. 客户端工具:curl 即可;需要格式化 JSON 时可接 python3 -m json.tool;
  3. 版本差异提醒: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/listGETRTSP 连接与会话(两级模型)
RTMP/SRT 连接/v3/rtmpconns/list、/v3/srtconns/listGETRTMP/SRT 连接(单级模型)
HLS 会话/v3/hlssessions/listGET在看的 HLS 播放会话
WebRTC 会话/v3/webrtcsessions/listGETWebRTC 会话
连接/会话踢出POST /v3/{rtspconns,rtspsessions,rtmpconns,srtconns,hlssessions,webrtcsessions}/kick/{id}POST断开指定连接/会话
全局配置/v3/config/global/get、/v3/config/global/patchGET/PATCH121 个全局参数读取与热更新
路径默认配置/v3/config/pathdefaults/getGET92 个 pathDefaults 参数
路径配置/v3/config/paths/{add,patch,remove}/{name}POST/PATCH/DELETE运行时增删改路径
指标:9998/metricsGETPrometheus 文本格式

约定: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>,这是服务端脱敏行为。

八、参考链接