基本说明
GBHub 国标视频平台对外提供一套 REST API,覆盖认证鉴权、设备/通道管理、流媒体启停、截图/云台/广播对讲、目录推送、代理与级联、定时任务、ONVIF 发现、移动端多用户、通话绑定等能力。
基础地址
http://<服务器IP>:3002
请求头
| 请求头 | 是否必需 | 说明 |
|---|---|---|
Authorization | 是 | JWT Bearer Token(除登录接口外) |
Content-Type | 写操作必需 | application/json |
X-Internal-Token | 内部接口必需 | 服务间调用鉴权 |
X-Node-Token | 节点上报 | /api/report-node-status 使用 |
关键约定
- JWT 有效期:默认 7 天(
JWT_EXPIRE_DAYS) - 通配符:统一使用
"*"(不再支持"all") - 时间格式:
YYYY-MM-DD HH:MM:SS或 ISO8601 - 分页:
page/page_size或cursor/count
通用错误码
| 状态码 / code | 含义 | 典型场景 |
|---|---|---|
| 200 | 成功 | 正常响应 |
| 401 | 认证失败 | 缺少或无效 JWT |
| 403 | 权限不足 | 无对应权限 |
| 404 | 资源不存在 | 设备/通道/任务不存在 |
| 422 | 请求体格式错误 | 字段缺失或类型不符 |
| 500 | 服务器内部错误 | 存储/后端异常 |
code: 0 | 业务成功 | 响应 JSON 中 code 字段 |
code: -1 | 业务错误 | 响应 msg 中含具体原因 |
1. 认证与 Token 管理
所有管理 API(除登录接口外)均需在请求头中携带 JWT:Authorization: Bearer <token>。默认初始化超级管理员 root,密码由 ADMIN_INIT_PASSWORD 指定(默认 admin123)。
1.1 管理员登录
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username* | String | 是 | 用户名 |
password* | String | 是 | 密码 |
curl -X POST http://127.0.0.1:3002/api/admin/login \ -H "Content-Type: application/json" \ -d '{"username":"root","password":"admin123"}'
响应示例
{"code":0,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}1.2 全局播放 / 推流 Token
全局 Token 由环境变量 PLAY_TOKEN / PUBLISH_TOKEN 控制,用于 ZLM 播放/推流鉴权,与管理 JWT 无关。
1.3 修改登录密码
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/change-pwd \ -H "Content-Type: application/json" \ -d '{"new_password":"new_password"}'
1.4 流专属 Token 管理
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/stream-token \ -H "Content-Type: application/json" \ -d '{"app":"live","stream":"test","type":"play","token":"my_token","expire_seconds":3600}'
2. ZLM 节点管理与 SIP 绑定
一个平台可挂载多台 ZLM 节点,每台 ZLM 的 hook 必须指向"管它设备的 SIP"。本节覆盖 ZLM 节点的增删改查、轮询、状态上报,以及 ZLM ↔ SIP 绑定。
2.1 获取节点列表
curl -H "Authorization: Bearer <token>" http://127.0.0.1:3002/api/zlm-servers
2.2 获取单个节点详情
2.3 更新节点
| 字段 | 类型 | 说明 |
|---|---|---|
name | String | 节点名称 |
api_base | String | ZLM API 地址 |
secret | String | ZLM API 密钥 |
http_fmp4_base | String | HTTP-FLV / fMP4 基地址 |
static_base | String | 静态资源基地址 |
record_virtual_path | String | 录像虚拟路径 |
media_ip | String | 媒体 IP |
curl -H "Authorization: Bearer <token>" -X PUT http://127.0.0.1:3002/api/zlm-servers/my-node-01 \ -H "Content-Type: application/json" \ -d '{"api_base":"http://new-api:9080","secret":"new-secret","http_fmp4_base":"http://192.168.28.252:9080/","static_base":"http://192.168.28.252:9080/","media_ip":"192.168.28.252"}'
2.4 删除节点
curl -H "Authorization: Bearer <token>" -X DELETE http://127.0.0.1:3002/api/zlm-servers \ -H "Content-Type: application/json" -d '{"id":"my-node-01"}'
2.5 轮询获取在线节点
2.6 节点状态上报
X-Node-Token(对应环境变量 NODE_REPORT_TOKEN)。首次上报会创建节点并异步设置所有 hook。2.7 绑定 SIP 节点
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/zlm-servers/my-node-01/bind-sip \ -H "Content-Type: application/json" -d '{"sip_node_id":"sip-01"}'
2.8 解绑 SIP 节点
3. 流媒体列表
curl -H "Authorization: Bearer <token>" \ "http://127.0.0.1:3002/api/zlm-media-list?node_id=my-node-01"
4. 实时播放
4.1 开启直播
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id | String | 否 | 通道 ID,不传则取设备第一个通道 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/start-live \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001"}'
4.2 停止直播
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/stop-live \ -H "Content-Type: application/json" \ -d '{"stream":"34020000001320000001_34020000001310000001"}'
5. 录像回放
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id | String | 否 | 通道 ID |
start_time* | String | 是 | 开始时间 |
end_time* | String | 是 | 结束时间 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/start-playback \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","start_time":"2026-06-01T10:00:00","end_time":"2026-06-01T11:00:00"}'
6. 云端录像管理
6.1 查询云端录像
node_id 字段,记录该录像文件所在的 ZLM 节点 ID。| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
channel_id | String | 否 | 通道 ID,不传则查全部通道 |
app | String | 否 | 应用名,默认 rtp |
start* | String | 是 | 开始时间(支持多种格式) |
end* | String | 是 | 结束时间 |
page | Integer | 否 | 页码,默认 1 |
page_size | Integer | 否 | 每页数量,默认 20 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/records \ -H "Content-Type: application/json" \ -d '{"channel_id":"34020000001310000001","app":"rtp","start":"2026-06-01 00:00:00","end":"2026-06-04 00:00:00","page":1,"page_size":10}'
响应示例
{
"code": 0,
"data": {
"records": [
{
"channel_id": "34020000001310000001",
"app": "rtp",
"start_time": "2026-07-21 09:02:06",
"end_time": "2026-07-21 09:02:30",
"file_path": "/etc/m/www/record/rtp/.../2026-07-21-17-02-06-0.mp4",
"file_size": 3615230,
"play_url": "http://192.168.28.252:9080/record/rtp/.../2026-07-21-17-02-06-0.mp4",
"node_id": "1",
"s3_url": null
}
],
"total": 290,
"page": 1,
"page_size": 10
}
}6.2 删除云端录像 DEPRECATED
cleanup_media),它会自动清理本地文件、数据库记录和 Redis S3 缓存,保证数据一致性。仅删除数据库元数据,不影响本地文件。
curl -H "Authorization: Bearer <token>" -X DELETE http://127.0.0.1:3002/api/records \ -H "Content-Type: application/json" \ -d '{"items":[{"channel_id":"34020000001310000001","app":"rtp","start_time":"2026-06-03T06:47:16","file_path":"/etc/.../xx.mp4"}]}'
7. 告警管理
7.1 查询告警记录
curl -H "Authorization: Bearer <token>" \ "http://127.0.0.1:3002/api/alarms?device_id=34020000001320000001&start_time=2026-06-06%2000:00:00&end_time=2026-06-07%2000:00:00"
7.2 删除告警记录
curl -H "Authorization: Bearer <token>" -X DELETE http://127.0.0.1:3002/api/alarms \ -H "Content-Type: application/json" \ -d '{"items":[{"device_id":"34020000001320000001","channel_id":"34020000001310000001","alarm_time":"2026-06-06T12:30:00"}]}'
8. 设备管理
8.1 获取所有设备列表
8.1.1 添加设备
在平台中注册一个新设备(NVR 或摄像头)。设备信息存储在 Redis 中,初始状态为离线(ip 和 port 为空),待设备主动注册或平台发起连接后更新。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 20 位国标设备编码(唯一) |
password | String | 否 | 设备注册密码(不填则使用全局配置) |
name | String | 否 | 设备自定义名称(便于识别) |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/devices \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","password":"123456","name":"NVR-主楼"}'
成功响应
{"code": 0, "msg": "device added successfully"}错误响应
| HTTP | 响应内容 | 说明 |
|---|---|---|
| 400 | {"code":-1,"msg":"device_id required"} | 缺少设备 ID |
| 409 | {"code":-1,"msg":"device already exists"} | 设备 ID 已存在 |
| 500 | {"code":-1,"msg":"internal error"} | Redis 操作失败 |
version=2016,传输协议为 tcp(推荐),同时创建空通道列表 device:{id}:channels = [],并加入全局集合 all_devices。设备上线后,ip 和 port 字段会被自动更新。8.2 分页获取设备列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
cursor | Integer | 否 | 游标,首次传 0,后续使用上一次返回的 next_cursor |
count | Integer | 否 | 每页条数,默认 200 |
8.3 搜索设备
智能判断:全数字按 ID 前缀匹配,否则按名称模糊匹配。
curl -H "Authorization: Bearer <token>" \ "http://127.0.0.1:3002/api/devices/search?keyword=340200000013"
8.4 获取设备通道列表(分页)
8.5 获取设备详细信息
8.6 刷新设备通道
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/refresh-device-channels \ -H "Content-Type: application/json" -d '{"device_id":"34020000001320000001"}'
8.7 修改设备配置
| 字段 | 类型 | 说明 |
|---|---|---|
device_id* | String | 设备 ID(必填) |
name | String | 设备名称 |
password | String | SIP 密码。特例:"0" 表示跳过鉴权(调试用),空串表示使用全局密码 |
transport | String | 媒体传输:udp / tcp。空/缺省时跟随注册上报的 auto_transport(推荐保留空,由设备自动探测) |
check_ssrc | Boolean | 是否启用 SSRC 校验,true/false,默认 false |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/device-config \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","name":"新名称","check_ssrc":"true","password":"新密码","transport":"tcp"}'
transport:空/缺省时跟随设备注册上报的 auto_transport;信令传输由设备注册时自动检测,无需手动设置。修改后生效时机:下一次拉起流时生效(ensure_stream_online 缓存会失效 10s 内的旧值)。8.8 删除设备
curl -H "Authorization: Bearer <token>" -X DELETE http://127.0.0.1:3002/api/devices \ -H "Content-Type: application/json" -d '{"device_id":"34020000001320000001"}'
8.9 查询设备状态历史
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
page | Integer | 否 | 页码,默认 1 |
page_size | Integer | 否 | 每页条数,默认 20,最大 200 |
items 为空。8.10 搜索设备通道
8.11 设备音频封装模式
设置设备在语音广播 / 双向对讲时使用的音频封装格式。ps 为默认(PT=96 + PS/90000),pcm 为 PCMA 裸流(PT=8 + PCMA/8000)。修改后下次发起广播/对讲时生效。
8.11.1 查询单通道当前配置
curl -H "Authorization: Bearer <token>" \ "http://127.0.0.1:3002/api/device/audio-ps?device_id=34020000001320000001&channel_id=34020000001310000001"
8.11.2 设置音频封装模式
# PS 封装(默认,兼容性最好) curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/device/audio-ps \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","mode":"ps"}' # PCMA 裸流(部分设备要求) curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/device/audio-ps \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","mode":"pcm"}'
8.11.3 重置为默认(PS)
9. 通道配置
9.1 查询单个通道配置
9.2 修改单个通道配置
| 字段 | 类型 | 说明 |
|---|---|---|
device_id* | String | 设备 ID |
channel_id* | String | 通道 ID |
substream | Boolean | 是否使用子码流,默认 false(主码流) |
zlm_node | String | 绑定的 ZLM 节点 ID(覆盖默认节点选择) |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/channel-config \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","substream":"true"}'
substream 或 zlm_node 后,正在进行的流不会自动切换,需要 stop-live 后重新 start-live 才生效。9.3 批量修改通道配置
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/channel-configs/batch \ -H "Content-Type: application/json" \ -d '{"channels":[{"device_id":"...","channel_id":"...","zlm_node":"node1"}]}'
10. 通道绑定与全局索引
10.1 获取绑定列表
10.2 绑定通道(单条)
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/channels \ -H "Content-Type: application/json" -d '{"id":"34020000001310000001","stream":"test","app":"live"}'
10.3 删除绑定
10.4 批量解绑
10.5 清空所有绑定
10.6 批量绑定
# 全部设备 curl -X POST "http://127.0.0.1:3002/api/channels/batch-bind" \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{"device_id":"*","app":"rtp"}' # 指定设备全部通道 curl -X POST "http://127.0.0.1:3002/api/channels/batch-bind" \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","app":"rtp"}'
10.7 获取全部设备通道
10.8 分页获取全部设备通道
10.9 通道自定义名称管理
10.10 手动刷新全局通道索引
11. 截图管理
11.1 请求设备截图(国标)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id | String | 否 | 通道 ID;不传则取设备第一个通道 |
version 字段自动选):version=2022:后端发
CaptureCmd 让设备直接上传到 S3 或本地;返回后立即 ready 或 pending。version=2016:后端发
Snapshot 查询,设备回 Base64 图片,后端保存到本地并返回 URL。
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/snapshot \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001"}'
11.2 ZLM 截图
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id | String | 条件 | 与 app+stream 二选一 |
channel_id | String | 条件 | — |
app | String | 条件 | 代理应用名 |
stream | String | 条件 | 代理流 ID |
zlm_node | String | 否 | 强制指定 ZLM 节点 |
count | Integer | 否 | 连拍次数,默认 1 |
async | Boolean | 否 | 走 ZLM 内部快速解码,默认 true |
11.3 查询最新截图
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
响应示例
{
"code": 0,
"data": {
"type": "file",
"url": "/snapshots/dev/xxx/20260601/143015_12345.jpg",
"sn": "12345",
"status": "ready",
"time": 1780300800
}
}| status | 含义 |
|---|---|
pending | 抓拍命令已发出,等待设备上传(前端应轮询直到 ready) |
ready | 已落盘/已上传 S3,URL 有效 |
none 或 data 缺失 | 该通道从未截图 |
11.4 截图历史列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
cursor | Integer | 否 | 游标(首次 0),默认 0 |
count | Integer | 否 | 每页数量,默认 50,最大 200 |
响应示例
{
"code": 0,
"data": {
"items": [
{
"url": "/snapshots/dev/xxx/20260601/143015_12345.jpg",
"date": "2026-06-01 14:30:15"
}
],
"next_cursor": 50,
"total": 128
}
}11.5 删除截图
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url* | String | 是 | 截图 URL(相对或绝对均可,S3 URL 也支持) |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/snapshot-delete \ -H "Content-Type: application/json" \ -d '{"url":"/snapshots/dev/xxx/20260601/143015_12345.jpg"}'
snapshot_index:{device_id}:{channel_id} 移除条目(清理任务会兜底)。11.6 批量截图
12. 云台控制
通过 POST /api/ptz 接口向设备发送云台控制指令。指令以十六进制字符串形式传递,支持持续按住和单次操作两种模式。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id | String | 否 | 通道 ID,不填则使用设备 ID |
ptz_cmd* | String | 是 | 云台控制码(十六进制字符串),见下表 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/ptz \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","ptz_cmd":"A50F01084C4C4095"}'
响应示例
{"code": 0}云台控制码
| 类型 | 操作 | Cmd 字符串 |
|---|---|---|
| 方向控制(持续按住时触发) | 上 | A50F01084C4C4095 |
| 下 | A50F01044C4C4091 | |
| 左 | A50F01024C4C408F | |
| 右 | A50F01014F4F4094 | |
| 单次操作(点击触发) | 放大 | A50F01424C000043 |
| 缩小 | A50F01444C004445 | |
| 停止 | A50F0100000000B5 |
13. 预置位管理
14. 语音广播与对讲 v0.9.7
音源编码:PCMA / G.711 A-law / 8000 Hz / 单声道(payload type 8)。
音源流:
stream 参数必须是 ZLM 上已存在的流(app=rtp)。模式配置:
BROADCAST_MODE = auto(默认)/ client / server。并发控制:同一通道同时只允许一个用户,通过
broadcast_owner:{device_id}:{channel_id} Redis 锁控制,锁 TTL 90s,前端每 30s 心跳续期。
14.1 单向语音广播(喊话)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID(20 位) |
channel_id* | String | 是 | 通道 ID(20 位) |
stream* | String | 是 | ZLM 上已存在的音源流(app=rtp) |
owner* | String | 是 | 前端生成的客户端唯一标识(UUID),用于独占锁 + 心跳续期。建议使用 crypto.randomUUID(),localStorage 持久化 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/audio-broadcast \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","stream":"talk_src_xxx","owner":"61cf1137-3e14-4eee-82ec-3a82c3a61d2d"}'
成功响应
{
"code": 0,
"stream_id": "talk_34020000001320000001_34020000001310000001",
"transport": "udp",
"status": "ready",
"answer_port": null,
"mode": "client"
}| 字段 | 类型 | 说明 |
|---|---|---|
stream_id | String | 会话 ID,格式 talk_{device_id}_{channel_id},停止/心跳必须携带 |
transport | String | tcp / udp,实际媒体传输方式 |
status | String | ready = 已在推流;waiting_device = TCP passive 等待设备主动连接 |
answer_port | Integer | null | TCP passive 监听端口;UDP 或 TCP active 为 null |
mode | String | client = 设备主动 INVITE(设备自推流);server = 服务器主动 INVITE |
14.1.1 心跳续期
broadcast_owner:{device_id}:{channel_id} 的 TTL 是 90s,前端必须每 30s 调一次续期。不调心跳的后果:90s 后锁过期,其他用户可抢占,自己的会话失效。
收到 423 时:说明锁已被别人抢走,前端应立即停止本地推流和播放。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
owner* | String | 是 | 必须与启动时相同 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/audio-broadcast-heartbeat \ -H "Content-Type: application/json" \ -d '{"device_id":"34020000001320000001","channel_id":"34020000001310000001","owner":"61cf1137-3e14-4eee-82ec-3a82c3a61d2d"}'
| code | 说明 |
|---|---|
0 | 续期成功(锁是自己的或首次写入) |
423 | 锁已被其他用户抢(自己的锁已过期,别人抢到了) |
-1 | 参数缺失 / Redis 异常 |
# 成功 {"code":0} # 锁被抢 {"code":423,"msg":"该通道已被其他用户占用","owner":"<current_owner>"}
14.1.2 停止广播
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
stream_id* | String | 是 | 启动时返回的 stream_id |
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
owner* | String | 是 | 必须与启动时相同,否则返回 423 拒绝释放 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/audio-broadcast-stop \ -H "Content-Type: application/json" \ -d '{"stream_id":"talk_xxx","device_id":"xxx","channel_id":"yyy","owner":"61cf1137-3e14-4eee-82ec-3a82c3a61d2d"}'
14.2 双向语音对讲
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
stream* | String | 是 | ZLM 上已存在的音源流 |
owner* | String | 是 | 独占锁 owner(与广播共用同一把锁) |
{
"code": 0,
"stream_id": "talk_34020000001320000001_34020000001310000001",
"recv_stream": "talk_recv_34020000001320000001_34020000001310000001",
"transport": "udp",
"status": "ready",
"answer_port": 45012,
"mode": "server"
}a=sendrecv)时返回,前端应播放 recv_stream 以听到设备回传音频。如果不支持双向:
recv_stream 为空字符串,前端可以退化为播放设备原流(play_url)。
14.2.1 停止对讲
14.3 常见错误
| code / HTTP | 响应 msg | 原因 / 解决 |
|---|---|---|
423 | 该通道正在被其他用户使用 | 独占锁冲突:别的用户正在广播/对讲。前端应提示并停止 |
-1 | device INVITE failed: src_stream 'xxx' not online in ZLM after 8s | 前端推流未成功(ZLM 上无此流)。检查 startPush 是否成功、麦克风权限、ZLM WebRTC 服务 |
-1 | startSendRtp failed: ... connection refused | 设备 SDP 是 TCP + a=setup:active,服务器无法主动连。改走 UDP 媒体 |
-1 | startSendRtp failed: can not find the source stream | stream 不在 ZLM 上。先推流再调 API |
-1 | client-only mode: device did not send INVITE | 设备未在 5s 内主动 INVITE。改用 BROADCAST_MODE=auto 或 server |
-1 | device INVITE failed: ...(reason: zlm_start_send_rtp_failed) | ZLM startSendRtp 失败。检查 ZLM 日志和 media_ip 配置 |
-1 | broadcast race unresolved: client result timeout | 设备 INVITE 处理超过 12s 仍未返回结果(罕见)。检查 server.rs 日志 |
-1 | device not found | 设备未注册 / 不在本 SIP 节点 |
-1 | no online zlm node | 无在线 ZLM 节点 |
14.4 前端实现要点
1.
startPush(stream) — 先推流(ZLM 上有流)2. 轮询 ZLM
getMediaList — 等流上线(可选,失败不阻塞)3.
POST /api/audio-broadcast — 推流就绪后再调 API4. 收到 423 → 前端
stopPush 回滚5. 每 30s 调
heartbeat — 续期锁6. 停止 →
POST stop + stopPush + close_streams不推荐(会死锁):先调 API 再推流。因为后端
handle_incoming_invite 会等前端推流上线(8s),前端等 API 返回 → 死锁。
15. 平台信息
16. 目录与业务分组管理
16.1 - 16.3 行政区域名称
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
code* | String | 是 | 行政区划代码 |
name* | String | 是 | 名称 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/admin-region-name \ -H "Content-Type: application/json" -d '{"code":"340200","name":"芜湖市"}'
16.4 - 16.6 业务分组名称
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
code* | String | 是 | 业务分组编码 |
name* | String | 是 | 名称 |
16.7 - 16.9 通道业务分组
17. 流代理管理
17.1 拉流代理
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
vhost | String | 否 | 默认 __defaultVhost__ |
app | String | 否 | 默认 live |
stream* | String | 是 | 流 ID |
url* | String | 是 | 拉流地址 |
on_demand | Boolean | 否 | 是否按需 |
zlm_node | String | 否 | 指定 ZLM 节点 |
enable_mp4 | Boolean | 否 | 是否开启 MP4 录制 |
auto_close | Boolean | 否 | 按需拉流无人观看自动关闭 |
17.2 推流代理
18. 录制控制
18.1 开始录制
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app* | String | 是 | 应用名 |
stream* | String | 是 | 流 ID |
type* | Int | 是 | 0=HLS, 1=MP4 |
customized_path | String | 否 | 保存目录 |
max_second | Int | 否 | 切片时长 |
19. 级联管理
用于管理下级平台与上级平台的级联连接,支持 UDP 和 TCP 两种传输方式。
19.1 获取级联列表
curl -H "Authorization: Bearer <token>" http://127.0.0.1:3002/api/servers
响应示例
{
"code": 0,
"data": [
{
"id": "182.92.251.233:6060",
"device_id": "34020000002000000004",
"realm": "3402000000",
"sip_server": "182.92.251.233:6060",
"local_addr": "0.0.0.0:5070",
"transport": "TCP"
}
]
}19.2 添加级联服务器
添加一个上级平台级联配置。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 下级设备 ID(用于 SIP 认证用户名) |
realm* | String | 是 | SIP 域 |
password* | String | 是 | 认证密码 |
sip_server* | String | 是 | 上级服务器地址(IP:端口) |
local_addr* | String | 是 | 本地监听地址(IP:端口),TCP 模式下为 TCP 监听端口 |
transport* | String | 是 | 传输协议:UDP 或 TCP |
version | String | 否 | GB/T 28181 协议版本,默认 "2022" |
server_id | String | 否 | 上级平台 ID,不传时使用 device_id |
UDP 模式示例
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/servers \ -H "Content-Type: application/json" \ -d '{ "device_id": "34020000002000000004", "realm": "3402000000", "password": "password123", "sip_server": "182.92.251.233:6060", "local_addr": "0.0.0.0:5070", "transport": "UDP", "version": "2022" }'
TCP 模式示例
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/servers \ -H "Content-Type: application/json" \ -d '{ "device_id": "34020000002000000004", "realm": "3402000000", "password": "password123", "sip_server": "182.92.251.233:6060", "local_addr": "0.0.0.0:5070", "transport": "TCP", "version": "2022" }'
成功响应
{"code": 0, "msg": "server added"}常见错误
| HTTP | 响应体 | 说明 |
|---|---|---|
| 400 | {"code":-1,"msg":"invalid tcp_source_addr"} | tcp_source_addr 格式错误 |
| 500 | {"code":-1,"msg":"TCP source port must not equal listening port"} | 源端口与监听端口相同 |
19.3 删除级联服务器
curl -H "Authorization: Bearer <token>" -X DELETE http://127.0.0.1:3002/api/servers \ -H "Content-Type: application/json" \ -d '{"id":"182.92.251.233:6060"}'
20. 系统备份与恢复
20.1 备份系统配置
导出所有代理配置、目录管理数据、通道绑定关系。
curl -H "Authorization: Bearer <token>" -X POST http://localhost:3002/api/backup/system -o backup.json
20.2 恢复系统配置
| 参数 | 类型 | 说明 |
|---|---|---|
clear_before | Boolean | 是否清空现有数据再恢复,默认 false |
stream_proxies | Array | 拉流代理数组(可选) |
stream_pusher_proxies | Array | 推流代理数组(可选) |
admin_region_names | Object | 行政区域名称(可选) |
biz_group_names | Object | 业务分组名称(可选) |
channel_biz_group | Object | 通道业务分组绑定(可选) |
channel_bindings | Object | 正向通道绑定(可选) |
channel_bindings_rev | Object | 反向通道绑定(可选) |
channel_names | Object | 通道自定义名称(可选) |
curl -H "Authorization: Bearer <token>" -X POST http://localhost:3002/api/restore/system \ -H "Content-Type: application/json" -d @backup.json
21. Webhook 回调(sip / zlm-node)
on_record_mp4)自 v0.9.1 起改由 zlm-node 处理。| 端点 | 监听方 | 用途 |
|---|---|---|
/hook/on_record_mp4 | zlm-node:3004 | 录像完成,上传 S3 并通知 mgr |
/hook/health | zlm-node:3004 | 健康检查,返回 ok |
/hook/on_stream_changed | sip | 流状态变化 |
/hook/on_play | sip | 播放鉴权 |
/hook/on_publish | sip | 推流鉴权 |
/hook/on_stream_none_reader | sip | 无人观看自动关闭 |
/hook/on_stream_not_found | sip | 触发自动拉流 |
/hook/on_rtp_server_timeout | sip | RTP 超时清理 |
/hook/on_server_started | sip | 恢复流代理 |
22. 定时任务管理
X-Internal-Token,仅供 scheduler 调用。调度器扫描间隔:30 秒。通配符:
"*"("all" 已废弃)。
22.1 创建定时任务
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
action* | String | 是 | snapshot / record / cleanup_sessions / sync_device_status / cleanup_media / cleanup_snapshot / cleanup_orphan_devices / cleanup_orphan_nodes / cleanup_transcribe_orphans |
cron_expr* | String | 是 | Cron 表达式(UTC) |
device_id | String | 条件 | "*" 表示全部设备 |
channel_id | String | 条件 | "*" 表示该设备全部通道 |
duration_secs | Integer | record 必填 | 录制时长 |
concurrency | Integer | 否 | 并发数,默认 5 |
retention_days | Integer | 否 | 清理任务保留天数,默认 7 |
22.1.1 常见示例
示例 1:每天凌晨 3 点清理所有 7 天前的录像
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/schedule/tasks \ -H "Content-Type: application/json" \ -d '{"action":"cleanup_media","cron_expr":"0 3 * * *","retention_days":7}'
示例 2:每天凌晨 4 点清理所有 7 天前的截图
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/schedule/tasks \ -H "Content-Type: application/json" \ -d '{"action":"cleanup_snapshot","cron_expr":"0 4 * * *","retention_days":7}'
示例 3:只清理 live 应用下 camera1 流的 7 天前录像
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/schedule/tasks \ -H "Content-Type: application/json" \ -d '{"action":"cleanup_media","cron_expr":"0 3 * * *","retention_days":7,"app":"live","stream":"camera1"}'
示例 4:每周日凌晨 5 点清理残留会话
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/schedule/tasks \ -H "Content-Type: application/json" \ -d '{"action":"cleanup_sessions","cron_expr":"0 5 * * 0"}'
22.2 清理任务行为
| 动作 | 清理范围 | 建议 Cron |
|---|---|---|
cleanup_media | 录像文件 + DB + Redis S3 缓存 | 0 3 * * * |
cleanup_snapshot | 截图文件 | 0 4 * * * |
cleanup_sessions | 残留级联会话 | 按需 |
cleanup_orphan_devices | 孤儿设备 | 0 0 3 * * 0 |
cleanup_orphan_nodes | 孤儿节点 | 0 0 4 1 * * |
cleanup_transcribe_orphans | 孤立转录 | 0 0 5 * * 0 |
22.2.1 设备状态同步任务
定时扫描所有设备,仅状态变化时写入 device_status_log。支持 callback_url 推送状态变化事件。
- 环境变量:
SYNC_BATCH_SIZE(默认 2000)、SYNC_MAX_ITERATIONS(默认 10)、DEVICE_OFFLINE_TIMEOUT_SECS(默认 180) - 自动清理:扫描过程中会自动移除
all_devices中的无效设备 ID
回调格式(当提供了 callback_url 时):
POST {callback_url}
Content-Type: application/json
{
"event": "device_status_changed",
"changes": [
{
"device_id": "34020000001320000001",
"previous_status": "ON",
"current_status": "OFF",
"ts": 1722225000
}
]
}22.2.2 Cron 表达式与时区
0 19 * * *。22.3 其它接口
23. 截图与辅助 API
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/start-record-task \ -H "Content-Type: application/json" \ -d '{"app":"live","stream":"test","path":"callback_test.mp4","back_ms":10000,"forward_ms":10000,"callback_url":"http://your-server.com/notify"}'
24. ONVIF 设备发现与代理
所有接口挂 proxy:manage 权限。底层实现委托给 ZLM 节点。建议与待发现设备同网段的 ZLM 节点才能搜到 ONVIF 组播响应。
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/onvif/search \ -H "Content-Type: application/json" \ -d '{"timeout_ms":5000,"subnet_prefix":"192.168.1.","zlm_node":"my-node-01"}'
zlm_node 必须显式指定!源码强制校验,不允许为空。25. 移动端多用户与通道分配
GBHub 支持为移动端 App 创建独立用户,每个用户可被分配 设备通道 或 拉流代理 的播放权限。移动端通过 JWT Bearer Token 认证,管理员通过 JWT 管理用户和权限。
.env 中设置 JWT_SECRET,默认有效期为 7 天(可通过 JWT_EXPIRE_DAYS 调整)。权限格式:设备通道使用
<device_id>:<channel_id>,拉流代理使用 proxy:<app>:<stream>。
25.0 可用权限列表
| 权限标识 | 说明 |
|---|---|
devices:read | 查看设备列表、设备详情、通道列表 |
devices:write | 添加/删除设备、修改设备配置、通道绑定/解绑、通道名称管理、设备音频封装模式 |
records:read | 查询云端录像 |
records:delete | 删除云端录像记录 |
alarms:read | 查询告警记录 |
alarms:delete | 删除告警记录 |
proxy:manage | 管理拉流代理、推流代理、FFmpeg 代理、ONVIF 操作 |
zlm:manage | 管理 ZLM 节点(增删改查、轮询) |
system:config | 系统配置:备份/恢复、定时任务、修改密码、平台信息 |
user:manage | 用户管理:创建/删除用户、修改用户权限、通道批量分配 |
snapshot | 请求截图、查询截图缓存 |
record:control | 手动控制录制(开始/停止/状态查询) |
ptz:control | 云台控制、预置位 |
audio:control | 语音广播与对讲 |
root 拥有以上全部权限。权限变更后即时生效,无需重启服务。25.1 管理员接口
25.1.1 列出所有用户
curl -H "Authorization: Bearer <token>" http://127.0.0.1:3002/api/admin/users
{
"code": 0,
"data": ["alice", "bob", "charlie"]
}25.1.2 创建用户
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username* | String | 是 | 用户名 |
password* | String | 是 | 密码(明文,服务端 Bcrypt 加密) |
permissions | Array | 否 | 权限列表,默认空数组 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/admin/users \ -H "Content-Type: application/json" \ -d '{"username":"alice","password":"secret123","permissions":["devices:read","records:read"]}'
25.1.3 删除用户
25.1.4 管理员修改用户密码
25.1.5 获取用户权限
25.1.6 更新用户权限(覆盖)
25.1.7 获取用户通道列表
{
"code": 0,
"data": [
{
"type": "device",
"device_id": "34020000001320000001",
"channel_id": "34020000001310000003",
"device_name": "NVR-01",
"channel_name": "摄像头01"
},
{
"type": "proxy",
"app": "live",
"stream": "camera1",
"name": "大门RTSP"
}
]
}25.1.8 分配通道权限(设备通道)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
channel_id* | String | 是 | 格式 <device_id>:<channel_id> |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/admin/users/alice/channels \ -H "Content-Type: application/json" \ -d '{"channel_id":"34020000001320000001:34020000001310000003"}'
25.1.9 移除通道权限(设备通道)
25.1.10 清理用户无效通道权限
自动扫描用户所有权限,移除那些设备已不存在、通道已删除或代理已失效的权限。
25.1.11 分配代理权限
25.1.12 移除代理权限
25.1.13 批量分配通道权限
25.1.14 列出代理通道 ID
25.2 移动端接口
25.2.1 登录
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username* | String | 是 | 用户名 |
password* | String | 是 | 密码 |
curl -X POST http://127.0.0.1:3002/api/mobile/login \ -H "Content-Type: application/json" \ -d '{"username":"alice","password":"secret123"}'
{
"code": 0,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}25.2.2 获取当前用户的通道列表
返回当前登录用户被授权的所有通道(包含设备通道和代理),同时附带播放地址、截图 URL 及是否有缓存截图。
{
"code": 0,
"data": [
{
"type": "device",
"device_id": "34020000001320000001",
"channel_id": "34020000001310000003",
"device_name": "NVR-01",
"channel_name": "摄像头01",
"play_url": "http://192.168.28.252:9080/rtp/34020000001320000001_34020000001310000003.live.mp4",
"snapshot_url": "http://static.example.com/snapshots/...",
"has_snapshot": true
},
{
"type": "proxy",
"app": "live",
"stream": "camera1",
"name": "大门RTSP",
"play_url": "http://192.168.28.252:9080/live/camera1.live.mp4",
"snapshot_url": "/api/mobile/snapshot?id=proxy:live:camera1",
"has_snapshot": false
}
]
}25.2.3 获取通道播放地址(自动截图)
返回指定通道的播放地址,并在后台异步触发截图(仅对国标设备有效,代理不会自动截图)。
| 路径参数 | 类型 | 说明 |
|---|---|---|
channel_id* | String | 格式 <device_id>:<channel_id> 或 proxy:<app>:<stream> |
snapshot:latest:<device_id>:<channel_id>)。若已有缓存或正在截图,则不会重复执行。25.2.4 移动端修改密码
25.2.5 移动端截图
主动请求通道截图,支持国标设备和拉流代理。对于代理,若流不在线则会尝试按需拉流,等待流上线后再截图。
| 查询参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | String | 条件必填 | 代理标识,格式 proxy:<app>:<stream>(与 device_id+channel_id 二选一) |
device_id | String | 条件必填 | 国标设备 ID |
channel_id | String | 条件必填 | 国标通道 ID |
26. 录像转录(Transcribe)
将指定设备通道的历史录像片段异步录制为 MP4 文件,并提供播放地址。任务在后台执行,支持去重、并发控制、取消和状态查询。
TRANSCRIBE_MAX_CONCURRENT 控制,默认 3 个任务。防重机制:同一
device_id + channel_id + start_time + end_time 的任务只会执行一次。原速录制:任务以原速拉取录像流,不会倍速处理。
26.1 启动转录任务
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 国标设备 ID |
channel_id* | String | 是 | 视频通道 ID |
start_time* | String | 是 | 开始时间 |
end_time* | String | 是 | 结束时间 |
zlm_node | String | 否 | 指定 ZLM 节点 |
callback_url | String | 否 | 转录完成回调地址 |
curl -H "Authorization: Bearer <token>" -X POST http://127.0.0.1:3002/api/playback/transcribe \ -H "Content-Type: application/json" \ -d '{ "device_id": "34020000001320000001", "channel_id": "34020000001310000003", "start_time": "2026-08-07 16:00:00", "end_time": "2026-08-07 16:30:00" }'
成功响应
{
"code": 0,
"msg": "transcribe task started",
"task_id": "550e8400-e29b-41d4-a716-446655440000"
}常见错误
| HTTP | code | msg |
|---|---|---|
| 400 | -1 | 缺少必填参数或时间格式错误 |
| 401 | -1 | 未授权(缺少或无效 JWT) |
| 409 | -1 | 任务已在运行中(同一时间段) |
| 429 | -1 | 并发任务数已达上限 |
{"code":0, "msg":"already transcribed", "file_url":"..."},不再创建新任务。26.2 停止转录任务
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id* | String | 是 | 任务 ID |
26.3 查询转录结果
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
device_id* | String | 是 | 设备 ID |
channel_id* | String | 是 | 通道 ID |
start_time* | String | 是 | 开始时间 |
end_time* | String | 是 | 结束时间 |
响应(已完成)
{
"code": 0,
"status": "completed",
"file_url": "http://192.168.28.252:9080/record/rtp/proxy_playback_.../xxx.mp4"
}响应(运行中)
{
"code": 0,
"status": "running",
"msg": "task is still in progress",
"task_id": "550e8400-e29b-41d4-a716-446655440000"
}响应(未找到)
{
"code": 0,
"status": "not_found",
"msg": "no transcription found for this time range"
}26.4 回调通知
POST {callback_url}
Content-Type: application/json
{
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"file_url": "http://192.168.28.252:9080/record/rtp/.../xxx.mp4"
}26.5 常见问题
404 Not Found,任务会在约 15 秒后超时失败,请先通过 /api/device-channels 确认正确的通道 ID。running,导致该时间段无法重新发起转录。可手动删除 Redis 键 transcribe:status:{core} 和 transcribe:task_id:{core} 后重试。27. 设备与通道统计
获取平台当前设备总数和通道总数,适合运维监控、仪表盘展示。采用 Redis Pipeline 优化,设备数 ≤ 1 万时响应迅速。
curl -H "Authorization: Bearer <token>" http://127.0.0.1:3002/api/stats/summary
成功响应
{
"code": 0,
"data": {
"device_count": 128,
"channel_count": 456
}
}| 字段 | 类型 | 说明 |
|---|---|---|
code | int | 0 表示成功,-1 表示失败 |
device_count | int | 已注册设备总数(来自 Redis 集合 all_devices 的基数) |
channel_count | int | 所有设备通道数量累加 |
错误响应
| HTTP | 响应体 | 说明 |
|---|---|---|
| 401 | {"code":-1,"msg":"unauthorized"} | 未认证或 JWT 无效 |
| 403 | {"code":-1,"msg":"forbidden"} | 权限不足 |
| 500 | {"code":-1,"msg":"internal error"} | Redis 异常或内部错误 |
28. 多 SIP 节点管理
平台支持挂载多个 SIP 节点。共享 Redis 架构下,心跳(sip_node:hb:*)和设备上报由 SIP 直接写 Redis,不经 mgr。
28.1 注册 SIP 节点(内部)
28.2 - 28.7 节点查询
28.8 - 28.10 级联操作
28.11 - 28.12 注销与推送
29. 内部接口与录像上传
以下接口仅供内部服务间调用,不对外暴露。除特别说明外,均需在请求头携带 X-Internal-Token: <INTERNAL_API_TOKEN>。
29.1 生成录像上传 Presigned URL
{"stream":"34020000001320000001_34020000001310000001","app":"rtp","vhost":"__defaultVhost__","file_path":"/opt/media/xxx.mp4"}29.2 录像完成事件通知
POST /internal/on-record-event;新:POST /api/internal/on-record-event29.3 录像链路整体流程
/hook/on_record_mp4zlm-node 侧:调 mgr
/api/internal/presign-record 拿 URL → PUT S3 → 删本地 → 调 /api/internal/on-record-event 通知入库mgr 侧:写库 + 通知前端
30. 通话绑定管理
用于管理「会议房间 → ZLM 节点」的绑定关系,是会议通话(对讲)的核心配置。自动绑定由 meeting 侧在会议创建时写入(TTL 30 分钟),管理员可通过本接口写入永久绑定(无 TTL)。
meeting:room:{room}:zlm,值 = ZLM 节点 ID。自动绑定:
SET NX EX 1800,有 TTL。手动绑定:
SET 无 EX,无 TTL,永久。列表返回 ttl_secs:
-1 表示永久,>0 表示剩余秒数,-2 表示 key 不存在。
30.1 列出所有绑定
curl -H "Authorization: Bearer <token>" \ http://127.0.0.1:3002/api/meeting/bindings
{
"code": 0,
"data": [
{ "room_id": "abc", "node_id": "node-1", "ttl_secs": -1 },
{ "room_id": "xyz", "node_id": "node-2", "ttl_secs": 1500 }
]
}30.2 查询单个房间的绑定
room_id 校验规则:非空、≤ 64 字符、只允许 [a-zA-Z0-9_-]。30.3 创建/更新绑定(永久)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
node_id* | String | 是 | ZLM 节点 ID,需存在且在线 |
1.
node_id 非空且 ≤ 64 字符;2. Redis 中
zlm_node:{node_id} 必须存在(否则返回 node not found);3.
node_id 必须在集合 zlm_nodes:online 中(否则返回 node not online)。
30.4 解除单个绑定
30.5 批量解除绑定
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
room_ids* | Array<String> | 是 | 房间 ID 列表,最多 1000 个;非法 ID 会被自动过滤 |
30.6 错误码
| HTTP / code | msg | 说明 |
|---|---|---|
| 200 / 0 | ok | 成功 |
| 200 / -1 | invalid room_id | room_id 非法 |
| 200 / -1 | invalid node_id | node_id 非法 |
| 200 / -1 | node not found | 节点不存在 |
| 200 / -1 | node not online | 节点离线 |
| 200 / -1 | room_ids required | 批量请求缺 room_ids |
| 200 / -1 | too many (max 1000) | 批量超过 1000 |
| 200 / -1 | no valid room_ids | 全部 room_id 非法 |
| 200 / -1 | internal error | Redis 异常 |
31. 变更记录
v0.9.7 NEW
- 语音广播/对讲补齐独占锁机制:新增
/api/audio-broadcast-heartbeat接口;audio-broadcast、audio-talk、audio-broadcast-stop、audio-talk-stop增加必填参数owner;新增响应字段stream_id/transport/status/answer_port/mode。 - 截图管理新增 3 个接口:
GET /api/snapshot-list、POST /api/snapshot-delete、GET /api/snapshot-query补齐参数表。 - device-config / channel-config 补字段表。
- 语音广播/对讲错误码补全。
- 前端实现要点:明确「先推流后 API」时序,避免死锁。
v0.9.6
- 新增「通话绑定管理」章节:
/api/meeting/bindings*五个接口。
v0.9.5
- 新增「设备音频封装模式」接口:
GET/POST/DELETE /api/device/audio-ps。
v0.9.4
- 对讲/广播 SIP 报文修复:SDP
m=audio端口从0改为设备返回的真实端口;Subject 头从<id>:<ssrc>,<id>:0改为<id>:<ssrc>;Broadcast Notify 后增加等待。 - 新增 TCP 入 INVITE 处理。
- 双模式仲裁:
BROADCAST_MODE=auto/client/server。
v0.9.3
- ZLM 截图接口新增
async参数,默认 true。 - 截图调用链统一改造。
- 修复 6 个 ZLM 接口 URL 参数未编码。
v0.9.2
- ZLM 节点管理补充完整接口。
- 新增 ZLM ↔ SIP 绑定。
- 新增「多 SIP 节点管理」章节。
v0.9.1
- 新增
mgr: POST /api/internal/presign-record。 - 新增
zlm-node: POST /hook/on_record_mp4、GET /hook/health。 - 路径变更:
/internal/on-record-event→/api/internal/on-record-event。 - schedule 新增 action:
cleanup_orphan_devices、cleanup_orphan_nodes、cleanup_transcribe_orphans。
v0.9.0
- 移动端多用户、通道批量分配、代理通道 ID 列表、录像转录、设备与通道统计、ONVIF、批量绑定、全局通道索引。