18 KiB
18 KiB
Owl(GoWVP)开源视频监控管理平台 API 调研报告
调研目标:为 Vol.Pro 后端对接 Owl 提供技术方案依据
仓库地址:https://github.com/gowvp/owl
调研日期:2026-05-06
一、API 认证方式
Owl 采用 JWT Token 认证机制,所有业务 API(除登录、健康检查、Webhook 回调外)均需在请求头中携带 Token。
1.1 登录获取 Token
- URL:
POST /login - 请求参数:
{ "data": "<RSA加密后的JSON字符串>" }- 加密前内容示例:
{"username":"admin","password":"admin"} - 公钥获取:
GET /login/key,返回 Base64 编码的 RSA 公钥(PEM 格式)
- 加密前内容示例:
- 响应示例:
{ "token": "eyJhbGciOiJIUzI1NiIs...", "user": "admin" } - Token 有效期: 3 天
- 使用方式: 请求头携带
Authorization: Bearer <token>
1.2 修改凭据
- URL:
PUT /users - 说明: 需先校验旧密码,同样使用 RSA 加密传输
二、设备管理 API
设备类型支持:
GB28181、ONVIF、RTMP、RTSP
2.1 设备列表查询
- URL:
GET /devices - 认证: 需 JWT
- 请求参数 (Query):
参数 类型 说明 pageint 页码,默认 1 sizeint 每页大小 keystring 关键词模糊搜索(名称/国标编号) - 响应:
{ "items": [ { "id": "gb_34020000001320000001", "type": "GB28181", "device_id": "34020000001320000001", "name": "NVR-01", "transport": "UDP", "stream_mode": 1, "ip": "192.168.1.100", "port": 5060, "is_online": true, "registered_at": "2026-05-06T10:00:00Z", "keepalive_at": "2026-05-06T10:05:00Z", "keepalives": 30, "expires": 3600, "channels": 4, "address": "192.168.1.100:5060", "password": "", "username": "", "ext": {} } ], "total": 100 }
2.2 设备详情
- URL:
GET /devices/:id - 响应: 单条 Device 对象(同上)
2.3 添加设备
- URL:
POST /devices - 认证: 需 JWT
- 请求体:
// GB28181 设备 { "type": "GB28181", "device_id": "34020000001320000001", "name": "摄像头1", "password": "123456" } // ONVIF 设备 { "type": "ONVIF", "ip": "192.168.1.100", "port": 80, "username": "admin", "password": "12345", "name": "ONVIF摄像头" } - 说明: GB28181 设备实际注册靠设备主动 SIP 注册,此接口用于预录入设备信息
2.4 修改设备
- URL:
PUT /devices/:id - 请求体 (
EditDeviceInput):字段 类型 说明 device_idstring 20 位国标编号 namestring 设备名称 passwordstring 注册密码 stream_modeint 0:UDP, 1:TCP_PASSIVE, 2:TCP_ACTIVE usernamestring ONVIF 用户名 ipstring ONVIF IP portint ONVIF 端口
2.5 删除设备
- URL:
DELETE /devices/:id
2.6 查询设备目录(刷新通道)
- URL:
POST /devices/:id/catalog - 说明: 向 GB28181 设备发送 Catalog 查询指令,拉取通道列表
- 响应:
{"msg": "ok"}(异步执行)
2.7 ONVIF 设备发现
- URL:
GET /onvif/discover - 说明: SSE 流式返回发现的 ONVIF 设备
三、通道管理 API
3.1 通道列表查询
- URL:
GET /channels - 认证: 需 JWT
- 请求参数 (Query):
参数 类型 说明 pageint 页码 sizeint 每页大小 didstring 父设备 ID device_idstring 国标编码 keystring 名称/国标编码模糊搜索,ID 精确搜索 is_onlinestring 是否在线过滤 typestring 通道类型:GB28181/ONVIF/RTMP/RTSP appstring 应用名 streamstring 流 ID - 响应:
{ "items": [ { "id": "gb_34020000001320000001_34020000001320000001", "did": "gb_34020000001320000001", "device_id": "34020000001320000001", "channel_id": "34020000001320000001", "name": "通道01", "ptztype": 1, "is_online": true, "is_playing": false, "type": "GB28181", "app": "rtp", "stream": "gb_34020000001320000001_34020000001320000001", "has_recording": true, "config": {} } ], "total": 100 }
3.2 设备与通道关联列表
- URL:
GET /devices/channels - 说明: 返回设备列表,每个设备包含
children(通道数组),并按在线状态排序 - 响应:
{ "items": [ { "id": "gb_xxx", "name": "NVR-01", "is_online": true, "children": [ { "id": "gb_xxx_xxx", "name": "通道01", "is_online": true, "has_recording": true } ] } ], "total": 10 }
3.3 添加通道(RTMP/RTSP)
- URL:
POST /channels - 请求体 (
AddChannelInput):{ "type": "RTMP", "name": "推流通道1", "device_id": "", "device_name": "", "app": "live", "stream": "stream01", "config": { "is_auth_disabled": false, "session": "", "media_server_id": "", "push_addr": "" } }
3.4 修改通道
- URL:
PUT /channels/:id - 请求体 (
EditChannelInput):字段 类型 说明 device_idstring 国标编码 namestring 通道名称 ptztypeint 云台类型 is_onlinebool 是否在线 extobject 扩展属性 appstring 应用名(RTMP/RTSP) streamstring 流 ID configStreamConfig 流配置
3.5 删除通道
- URL:
DELETE /channels/:id - 限制: 仅允许删除 RTMP/RTSP 类型通道
四、实时流地址获取 API
4.1 获取播放地址
- URL:
POST /channels/:id/play - 认证: 需 JWT
- 说明: 根据通道类型自动处理拉流逻辑
- GB28181: Owl 通过 SIP 邀请设备推流到 ZLM,自动开启 RTP Server
- RTMP: 检查是否已推流,直接从 ZLM 获取播放地址
- RTSP: 通过 ZLM 添加流代理(AddStreamProxy),再返回地址
- ONVIF: 直接从 ZLM 获取播放地址
- 响应 (
playOutput):{ "app": "rtp", "stream": "gb_34020000001320000001_34020000001320000001", "items": [ { "label": "ZLM", "ws_flv": "ws://host:port/proxy/sms/rtp/gb_xxx.live.flv", "http_flv": "http://host:port/proxy/sms/rtp/gb_xxx.live.flv", "rtmp": "rtmp://host:port/rtp/gb_xxx", "rtsp": "rtsp://host:port/rtp/gb_xxx", "webrtc": "webrtc://host:port/proxy/sms/index/api/webrtc?app=rtp&stream=gb_xxx&type=play", "hls": "http://host:port/proxy/sms/rtp/gb_xxx/hls.fmp4.m3u8" } ] }
4.2 停止播放
- URL:
POST /channels/:id/stop - 说明: 幂等操作,始终返回成功
- GB28181: 发送 SIP BYE + 关闭 ZLM RTP Server
- ONVIF/RTSP/RTMP: 调用 ZLM
close_streams关闭流
- 响应:
{"msg": "ok"}
4.3 快照相关
- 刷新快照:
POST /channels/:id/snapshot- 请求体可指定
within_seconds(秒内有效则返回缓存)和url(指定取流地址) - 响应:
{"link": "http://host/channels/:id/snapshot?token=xxx"}
- 请求体可指定
- 获取快照图片:
GET /channels/:id/snapshot?token=xxx- 直接返回 JPEG 图片流
五、回放流地址获取 API(云录像)
Owl 的录像回放功能由 Owl 自身管理(非设备 SD 卡录像),底层依赖 ZLM 的 MP4 录制。
5.1 查询录像列表
- URL:
GET /recordings - 认证: 需 JWT
- 请求参数 (Query):
参数 类型 说明 pageint 页码 sizeint 每页大小 cidstring 通道 ID appstring 应用名 streamstring 流 ID start_msint64 开始时间戳(毫秒) end_msint64 结束时间戳(毫秒) - 响应:
{ "items": [ { "id": 1, "cid": "gb_xxx_xxx", "app": "rtp", "stream": "gb_xxx_xxx", "started_at": "2026-05-06T10:00:00Z", "ended_at": "2026-05-06T10:05:00Z", "duration": 300.5, "path": "/recordings/rtp/gb_xxx_xxx/20260506/xxx.mp4", "size": 10485760 } ], "total": 50 }
5.2 获取时间轴
- URL:
GET /recordings/timeline?cid=xxx&start_ms=xxx&end_ms=xxx - 响应:
{ "items": [ { "id": 1, "start_ms": 1714982400000, "end_ms": 1714982700000, "duration": 300.5 } ] }
5.3 获取月度统计
- URL:
GET /recordings/monthly?cid=xxx&year=2026&month=5 - 响应:
{ "year": 2026, "month": 5, "days": 31, "has_video": "101010..." // 每天是否有录像,'1'有/'0'无 }
5.4 HLS 回放播放
- URL:
GET /recordings/channels/:cid/index.m3u8?start_ms=xxx&end_ms=xxx&token=xxx - 说明: 动态生成 m3u8 播放列表,将指定时间范围内的多个 MP4 片段拼接为 HLS (VOD)
- Content-Type:
application/vnd.apple.mpegurl
5.5 下载录像
- URL:
GET /recordings/:id/download - 说明: 返回 MP4 文件流,支持 HTTP Range 请求(边下载边播放)
5.6 静态文件播放
- URL:
GET /static/recordings/{path}?token=xxx - 说明: 直接访问 MP4/fMP4 文件,同样支持 Range 请求
六、云台控制 API
6.1 PTZ 控制
- URL:
POST /channels/:id/ptz/control - 认证: 需 JWT
- 请求体 (
ptzControlInput):字段 类型 必填 说明 actionstring 是 动作类型: continuous/stop/absolute/relative/presetdirectionstring 否 方向(continuous 时用): up/down/left/right/zoom_in/zoom_outspeedfloat64 否 速度 0-1 xfloat64 否 X 轴位置(absolute/relative) yfloat64 否 Y 轴位置 zoomfloat64 否 缩放值 preset_idstring 否 预置位 ID preset_opstring 否 预置位操作: goto/set/remove - 当前实现限制: 代码中仅实现了
continuous和stop,其他动作类型会返回错误 - 响应:
{ "msg": "PTZ 控制指令已发送" } - 注意: 目前代码中直接调用 GB28181 Server 的 PTZControl 方法,未区分协议类型(ONVIF PTZ 支持标记为 TODO)
七、设备状态查询 API
7.1 在线状态
Owl 没有单独的"设备状态查询"接口,设备状态包含在设备/通道列表查询中:
- 设备在线状态:
GET /devices或GET /devices/:id→is_online - 通道在线状态:
GET /channels或GET /devices/channels→is_online - 通道播放状态:
is_playing
7.2 设备模型关键状态字段
| 字段 | 说明 |
|---|---|
is_online |
是否在线(SIP 注册成功且心跳正常) |
registered_at |
最近一次注册时间 |
keepalive_at |
最近一次心跳时间 |
keepalives |
心跳间隔(秒) |
expires |
注册有效期(秒) |
address |
设备网络地址(如 192.168.1.100:5060) |
transport |
信令传输协议(UDP / TCP) |
channels |
通道数量 |
7.3 注册与心跳机制(SIP 层)
- 注册: GB28181 设备主动向 Owl 的 SIP 端口(默认 5060)发送 REGISTER 请求
- Owl 支持 Digest 鉴权,密码可设备单独配置或使用全局默认密码
- 注册成功后 Owl 自动查询 DeviceInfo 和 Catalog
- 心跳: 设备按
Keepalives间隔发送 MESSAGE 心跳- Owl 通过
keepalive_at和expires判断设备是否离线 - 例如:设备侧超时 3 秒 × 3 次,则约 9+x 秒收不到心跳认为离线
- Owl 通过
- 注销: 设备发送 Expires=0 的 REGISTER 请求
重要: 注册和心跳是 SIP 协议层自动完成的,没有对应的 HTTP API。Vol.Pro 只需通过 HTTP API 查询设备列表即可获知在线状态。
八、Owl 与 ZLMediaKit 联动机制
8.1 架构关系
摄像机/NVR --(SIP/RTP)--> Owl --(HTTP API/Webhook)--> ZLMediaKit
^
| (反向代理播放)
前端播放器 --(HTTP/WebSocket)---> Owl /proxy/sms/xxx
8.2 Owl 配置 ZLM 的 Hook 回调
Owl 启动时会自动连接 ZLM,并通过 SetServerConfig 接口设置以下 Webhook 地址(前缀为 http://{owl_host}:{owl_port}/webhook):
| Hook 接口 | 方法 | 说明 |
|---|---|---|
/webhook/on_server_started |
POST | ZLM 启动时触发,Owl 将所有 RTMP 通道置为离线 |
/webhook/on_server_keepalive |
POST | ZLM 定时保活(默认 10s),Owl 更新节点在线状态 |
/webhook/on_publish |
POST | 推流鉴权(RTMP/RTSP/RTP),Owl 校验是否允许推流 |
/webhook/on_play |
POST | 播放鉴权,Owl 更新通道播放状态为 playing |
/webhook/on_stream_changed |
POST | 流注册/注销时触发,Owl 根据录像模式决定是否启动录制 |
/webhook/on_stream_none_reader |
POST | 无人观看时触发,Owl 根据录像模式决定是否关闭流 |
/webhook/on_stream_not_found |
POST | 播放不存在的流时触发,Owl 触发按需拉流(ONVIF/RTSP) |
/webhook/on_rtp_server_timeout |
POST | RTP Server 超时未收到数据 |
/webhook/on_record_mp4 |
POST | MP4 切片录制完成,Owl 将录像信息入库 |
8.3 Owl 调用 ZLM 的 API
通过 internal/core/sms/driver_zlm.go 封装调用:
| ZLM API | Owl 封装方法 | 说明 |
|---|---|---|
openRtpServer |
OpenRTPServer |
开启 RTP 收流端口(GB28181 用) |
closeRtpServer |
CloseRTPServer |
关闭 RTP 端口 |
close_streams |
CloseStreams |
强制关闭流 |
addStreamProxy |
AddStreamProxy |
添加 RTSP 拉流代理 |
getSnap |
GetSnapshot |
获取流截图 |
startRecord |
StartRecord |
开始 MP4 录制 |
stopRecord |
StopRecord |
停止 MP4 录制 |
getServerConfig |
GetServerConfig |
获取配置(含端口信息) |
setServerConfig |
SetServerConfig |
设置配置(含 Hook 地址) |
restartServer |
RestartServer |
重启 ZLM(rtc 端口变更时) |
8.4 播放地址生成规则
Owl 通过反向代理 /proxy/sms/*path 将所有播放请求转发到 ZLM,前端无需直接访问 ZLM。
生成逻辑(GetStreamLiveAddr):
| 协议 | URL 格式示例 |
|---|---|
| WS-FLV | ws://owl_host/proxy/sms/{app}/{stream}.live.flv |
| HTTP-FLV | http://owl_host/proxy/sms/{app}/{stream}.live.flv |
| HLS(fMP4) | http://owl_host/proxy/sms/{app}/{stream}/hls.fmp4.m3u8 |
| WebRTC | webrtc://owl_host/proxy/sms/index/api/webrtc?app={app}&stream={stream}&type=play |
| RTMP | rtmp://owl_host:1935/{app}/{stream} |
| RTSP | rtsp://owl_host:554/{app}/{stream} |
8.5 联动流程示例(GB28181 实时播放)
- 前端调用
POST /channels/:id/play - Owl 向 ZLM 调用
openRtpServer开启 UDP/TCP 收流端口 - Owl 通过 SIP 发送 INVITE 给设备,SDP 中携带 ZLM 的收流地址
- 设备通过 RTP 向 ZLM 推流
- ZLM 触发
on_publish→on_stream_changedHook - Owl 返回包含播放地址的 JSON 给前端
- 前端通过
/proxy/sms/...播放流 - 无人观看时,ZLM 触发
on_stream_none_reader - Owl 判断无需录像 → 返回
Close: true→ ZLM 关闭流 - Owl 发送 SIP BYE 结束会话
九、其他相关 API
9.1 流媒体服务器管理
GET /media_servers- 查询媒体服务器列表PUT /media_servers/:id- 修改媒体服务器配置
9.2 推流管理
GET /stream_pushs- 查询推流列表(含 RTMP 推流地址)POST /stream_pushs- 添加推流PUT /stream_pushs/:id- 修改推流DELETE /stream_pushs/:id- 删除推流
9.3 事件/告警管理
GET /events- 分页查询 AI 检测事件GET /events/:id- 事件详情GET /events/image/*path- 获取事件快照图片(无需认证)
9.4 配置管理
GET /configs/info- 获取 SIP 等配置信息PUT /configs/info/sip- 修改 SIP 配置
9.5 系统接口
GET /health- 健康检查GET /app/metrics/api- API 实时监控指标GET /app/version/check- 检查新版本
十、Vol.Pro 对接建议
10.1 对接方式
Vol.Pro 后端直接通过 HTTP REST API 调用 Owl,无需处理 SIP 协议。
10.2 关键对接流程
1. 登录 Owl → 获取 JWT Token(缓存)
2. 定时同步设备列表 → GET /devices
3. 定时同步通道列表 → GET /channels 或 GET /devices/channels
4. 用户点击播放 → POST /channels/:id/play → 获取播放地址 → 前端播放
5. 用户停止播放 → POST /channels/:id/stop
6. 回放查询 → GET /recordings?cid=xxx&start_ms=xxx&end_ms=xxx
7. 回放播放 → GET /recordings/channels/:cid/index.m3u8?start_ms=xxx&end_ms=xxx
8. 云台控制 → POST /channels/:id/ptz/control
10.3 注意事项
- Token 管理: JWT 有效期 3 天,建议在 Vol.Pro 中缓存并处理过期刷新
- 播放地址代理: 前端播放地址建议走 Owl 的
/proxy/sms/...路径,无需暴露 ZLM 直接地址 - 按需拉流: GB28181 实时播放是按需拉流,首次播放可能有 1-3 秒延迟(SIP 信令 + ZLM 准备)
- 录像模式: 通道支持
always/ai/none三种录像模式,通过POST /channels/:id/record_mode设置 - PTZ 限制: 当前 Owl 仅支持
continuous(持续移动)和stop(停止),预置位等功能未完整实现 - 心跳与注册: 不要尝试通过 HTTP 模拟设备注册,这是 SIP 层自动完成的
- ONVIF PTZ: README 中标记为"未支持"(
[ ] ONVIF PTZ control support)
报告整理完毕,供 Vol.Pro 后端架构设计参考。