通信协议
通信概述
国标监控与设备走 GB/T 28181-2016 定义的 SIP 信令(基于 RFC 3261),与流媒体服务走 HTTP REST + Webhook 回调。本节列出实际报文格式与核心交互流程的时序图,所有报文均符合国标公开规范。
一、SIP 基础参数
| 项 | 值 |
|---|---|
| 端口 | UDP + TCP 5060(双栈) |
| 字符集 | GB2312(默认,可切换 UTF-8) |
| 鉴权方式 | Digest MD5(RFC 2617),支持 qop=auth 增强模式 |
| 心跳 | MESSAGE Keepalive(默认 60s 间隔,3 次超时) |
| 注册有效期 | 默认 3600s |
| 信令 Content-Type | Application/MANSCDP+xml |
| 回放控制 Content-Type | Application/MANSRTSP |
| INVITE Content-Type | application/sdp |
二、设备注册 + Digest 鉴权
Digest 计算两种模式:
qop=auth(RFC 2617 增强,雪亮工程 / 政务上级常用):
HA1 = MD5(username:realm:password)
HA2 = MD5(method:uri)
response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
简化模式(RFC 2069,部分老固件):
response = MD5(HA1:nonce:HA2)平台解析上级 401 响应的 qop 字段,自动选择对应计算方式,nc / cnonce 自动生成。
注册成功 200 OK 携带国标校时 Date
注册校验通过的 200 OK 携带 Date 头供依赖 SIP 注册校时的设备对时,格式为 GB/T 28181-2016 §7.10/§9.10 规定的 yyyy-MM-dd'T'HH:mm:ss.SSS 北京时间(非 jain-sip 默认的 RFC 1123 GMT),故以扩展头方式写入,避免 ISO 风格解析的设备校时失败或时区偏 8 小时。
安全加固:拒绝静默降级
平台 401 始终下发 qop="auth"。校验设备应答时:
- 回带
qop=auth的报文必须携带nc/cnonce(RFC 2617 §3.2.2),缺失即拒绝,不回退到无 cnonce 防重放的 RFC 2069 旧式; qop=auth-int同样拒绝;- 仅对完全不带 qop 的老固件才接受 RFC 2069 简化摘要(
response = MD5(HA1:nonce:HA2))。
如此避免"声明增强模式却因字段缺失静默降级"反而削弱安全性。
三、Catalog 同步
3.1 主动查询(Query / Response)
空目录与全量对账
设备显式应答 SumNum=0(空挂载 NVR / 通道全删后重新全量查询)时即判定同步完成,不再死等;全量查询完成后平台按本次收齐的通道集合对账,把设备侧已移除的旧通道置为离线(OFF),避免幽灵通道长期残留。
Catalog Item 字段(GB28181-2016 §A.2):
| 字段 | 说明 |
|---|---|
DeviceID | 通道国标编号(20 位) |
Name / Manufacturer / Model | 通道名 / 厂商 / 型号 |
CivilCode | 行政区划码,平台据此自动建分组树 |
Parental / ParentID | 是否为子目录 / 父节点编号(NVR 子通道) |
Status | 通道在线状态 |
Longitude / Latitude | 经纬度 |
Event | 订阅 NOTIFY 增量推送时携带:ADD / DEL / UPDATE / ON / OFF / VLOST / DEFECT |
3.2 订阅模式增量推送
订阅自动续约
平台每 30 分钟扫描"距过期 < 1 小时"的订阅,优先走 in-dialog SUBSCRIBE refresh(RFC 6665 §4.1.2.1),失败回退为新建订阅。 设备重连(REGISTER)时自动重发该设备所有 ACTIVE 订阅,避免设备视角订阅丢失。
四、实时点播(INVITE + SDP)
INVITE 必选头域(国标 §9.6.1):
INVITE sip:34020000001320000003@192.168.1.100:5060 SIP/2.0
From: <sip:34020000002000000001@3402000000>;tag=xxxx
To: <sip:34020000001320000003@3402000000>
Call-ID: ...
CSeq: 1 INVITE
Contact: <sip:34020000002000000001@10.0.0.1:5060> ← 必选,RFC 3261 §8.1.1.8
Subject: 34020000001320000003:0345670001,34020000002000000001:0 ← 必选,国标 §9.6.1
Content-Type: application/sdpSubject 头格式: <媒体流发送者ID:发送方流序号>,<媒体流接收者ID:接收方流序号>
- 第一段:媒体流发送者(被点播的设备通道 ID)+ 发送方流序号 = SDP
y=行的 10 位 SSRC - 第二段:媒体流接收者(本平台 server-id)+ 接收方流序号 固定
0
流序号 ≠ 主子码流编号
业内常见误解:把"流标识号"理解为 0=主码流 / 1=子码流。实际国标 §9.6.1 规定发送方流序号取 SDP y= 行 SSRC,严格上级 / 雪亮工程网关会以"Subject 中 SSRC 与 SDP y= 不一致"为由直接拒收(400 Bad Request)。主子码流通过 SDP 中的 a=streamnumber / a=streamprofile 表达。
SDP body 示例(主码流):
v=0
o=34020000002000000001 0 0 IN IP4 10.0.0.1
s=Play
c=IN IP4 10.0.0.1
t=0 0
m=video 30000 RTP/AVP 96 98 97 99
a=recvonly
a=streamnumber:0 ← 海康/大华/宇视通用
a=streamprofile:0 ← 大华额外字段(streamprofile 与 streamnumber 同义)
a=rtpmap:96 PS/90000
a=rtpmap:98 H264/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:99 H265/90000 ← H.265 over RTP,RFC 7798 / 国标 §C.6.4
y=0345670001 ← 10 位 SSRC(国标 §D.3.1)H.265 payload type 99
GB28181-2016 §C.6.4 把 H.265(HEVC)payload type 固定为 99。2022 年后新出厂 IPC 主码流大量默认 H265,SDP m= 行缺 99 会让严格设备直接 488 Not Acceptable 拒绝点播 / 回放。本实现点播 / 回放 SDP 一律下发 96 98 97 99 四种 payload。
主子码流多厂商兼容
GB28181 国标未规定主子码流字段,各厂商扩展不一:
- 海康/大华:
a=streamnumber - 大华另外支持:
a=streamprofile - 其他厂商:
a=stream:0/1或a=stream:MAIN/SUB
业内通用做法是同时下发多种(SDP 规范允许自定义 a= 行,设备不识别会自动忽略), 参考 LiveGBS / WVP-pro / ZLMediaKit 实践。本实现同时下发 streamnumber + streamprofile, 子码流场景额外携带 i=Stream:1(部分海康老款固件用 i= 行识别)。
五、历史回放 INVITE + INFO MANSRTSP
5.1 回放 INVITE
回放与点播流程相同,仅 SDP 不同:
s=Playback ← 区分实时(Play) / 回放(Playback) / 下载(Download)
u=34020000001320000003:0 ← 通道编号 + 录像类型(0=全部 / 1=手动 / 2=报警 / 3=定时)
t=1716624000 1716627600 ← Unix 秒级起止时间
y=1345670001 ← 回放 SSRC 前缀=1(历史媒体)5.2 回放控制(INFO MANSRTSP)
MANSRTSP body 模板(GB28181-2016 附录 P):
PLAY MANSRTSP/1.0
CSeq: 2
Range: npt=now-
PAUSE MANSRTSP/1.0
CSeq: 3
PauseTime: now
PLAY MANSRTSP/1.0
CSeq: 4
Scale: 2.000000 ← 倍速 0.25/0.5/1/2/4协议版本字符串 ≠ RTSP/1.0
MANSRTSP 是国标在 RTSP(RFC 2326)基础上裁剪定义的子集,起始行版本号必须是 MANSRTSP/1.0。若沿用 RTSP/1.0,严格设备会因方法行无法识别返回 400 / 505。本实现 CSeq 在同一 SSRC 会话内单调递增,与 GB28181-2016 附录 P / RFC 2326 §12.17 一致。
5.3 录像下载(s=Download 加速取流)
用户主动下载历史录像走国标 Download 会话(区别于实时回放 Playback),SDP 增加 a=downloadspeed 声明加速倍速,设备据此快于实时速率发送录像流,显著缩短长录像的取流耗时与端口/会话占用:
s=Download
u=34020000001320000003:0
t=1716624000 1716627600
a=downloadspeed:4 ← 4 倍速下载(可配置;设备不支持时退化为实时速率)
y=1345670001 ← 历史媒体 SSRC 前缀=1平台侧由流媒体录制为 MP4 后异步上传 OSS。下载完成判定轮询流媒体源流是否已下线(设备发完整段录像即结束推流),并以 录像时长 + 30s 封顶兜底,既适配加速也兼容忽略 downloadspeed 的设备。
六、PTZ 控制(GB28181 §A.3)
8 字节 PTZ 命令格式(GB/T 28181-2016 附录 A.3,与本实现 PtzCmdBuilder 一致):
Byte: 0 1 2 3 4 5 6 7
内容: A5 0F addr cmd hSpeed vSpeed zSpeed<<4 checksum
固定 固定 默认 1 方向 / 缩放 水平速度 垂直速度 缩放速度高 4 位 前 7 字节求和 & 0xFFcmd 字节各 bit 含义(GB/T 28181-2016 附录 A.3 控制码位定义):
| bit | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|
| 含义 | 变倍缩小 | 变倍放大 | 上 | 下 | 左 | 右 |
cmd = 0x00 表示停止。本实现协议层只暴露 4 个正交方向 + 2 个缩放,不下发斜向组合(主流固件对组合方向响应不一致)。 速度范围 0-255;缩放速度取高 4 位,非零变倍请求保证至少 1 级变倍速度(避免小速值整除后被压成 0 致设备不变倍);校验码为前 7 字节算术和 & 0xFF。
预置位 set / call / remove 走独立的 cmd 字节(0x81 / 0x82 / 0x83),预置位号写入 Byte 5(0-255),其余字节置 0。
七、报警上行(Notify + 订阅)
7.1 报文格式
<?xml version="1.0" encoding="GB2312"?>
<Notify>
<CmdType>Alarm</CmdType>
<SN>1</SN>
<DeviceID>34020000001320000003</DeviceID>
<AlarmPriority>4</AlarmPriority>
<AlarmTime>2026-05-26T10:00:00</AlarmTime>
<AlarmMethod>5</AlarmMethod> <!-- 5=视频报警 -->
<Longitude>116.40739</Longitude>
<Latitude>39.9042</Latitude>
<Info>
<AlarmType>6</AlarmType> <!-- AlarmMethod=5 时 6=入侵检测 -->
<AlarmTypeParam>
<EventType>1</EventType> <!-- 1=进入区域 / 2=离开区域 -->
</AlarmTypeParam>
</Info>
</Notify>AlarmMethod / AlarmType 联合语义(国标重点)
AlarmMethod 是顶层单值枚举(非位掩码):
- 1=电话 / 2=设备 / 3=短信 / 4=GPS / 5=视频 / 6=设备故障 / 7=其他
AlarmType 是二级枚举,语义跟随 AlarmMethod:
- AlarmMethod=2: AlarmType ∈
- AlarmMethod=5: AlarmType ∈
- AlarmMethod=6: AlarmType ∈
回调接口强制要求 alarmMethod + alarmType 成对传递,下游必须二者结合才能解释告警类型。 AI 智能事件主路径走 AlarmMethod=5 + AlarmType∈{2,5,6,7,8,12}。
7.2 流程
八、国标级联(作为下级)
qop=auth 兼容
雪亮工程 / 政务上级常强制 qop=auth(RFC 2617 增强模式), 下级若仅实现 RFC 2069 (response = MD5(HA1:nonce:HA2)) 会陷入 401 循环。 本实现解析 WWW-Authenticate.qop,支持两种模式自动切换。
401 重试必须复用 Call-ID
RFC 3261 §22.4 规定 401 challenge 后二次注册必须复用首次 REGISTER 的 Call-ID 并使 CSeq 递增,否则严格上级会将二次注册视为新事务再次返回 401,陷入死循环。本实现的 CascadeRegistrar 在第二轮 sendUpstreamRegister 时显式透传 originalCallId,与单元测试 CascadeRegistrarTest 一致。
九、流媒体 Webhook 与 RTP 收流
9.1 收流流程
设备 RTP/PS 流 (UDP 或 TCP 30000-40000)
↓ SSRC 匹配
流媒体服务接收
↓ on_stream_changed Hook
平台业务层
↓ 按 SSRC 反查会话(无需 JWT,业务层 ignore 后注入租户)
平台填 flv/hls/ws-flv/rtmp URL,会话转 RUNNING9.2 关键 Hook 端点
| Hook(平台对外暴露的实际路径) | 用途 | 处理 |
|---|---|---|
POST /blade-iot/vms/webhook/on_publish | RTP 推流到达鉴权 | 校验 secret 后返回 {"code":0} 放行(app/stream 已由 openRtpServer 预先约定);缺该端点会致流媒体每次推流命中 404,部分版本按鉴权失败拒绝发布致点播无画面 |
POST /blade-iot/vms/webhook/on_stream_changed | 流变更(注册 / 注销) | regist=true → 填 WS-FLV / HLS / RTMP URL + 转 RUNNING;regist=false → 转 CLOSED(忽略 CLOSE_PENDING / EXPIRED) |
POST /blade-iot/vms/webhook/on_stream_none_reader | 无人观看 | 实时点播(invite)立即关流并补发设备 BYE 终结其 INVITE 会话与 RTP 推流(防设备持续推流泄漏并占满槽位);回放(playback)保留流让用户暂停 30s 内不被回收 |
POST /blade-iot/vms/webhook/on_server_keepalive | 节点心跳 | ZLM 周期上报 mediaServerId,平台回写对应媒体节点 last_keepalive_time,驱动节点在线状态(在线判定窗口默认 60s);mediaServerId 须等于节点编码 node-id |
Hook 安全
平台启动期强制 vms.gb28181.zlm.hook-secret 非空(否则 fail-fast),所有 webhook 报文经 query 参数 ?secret= 校验。可选 allowed-hook-ips CSV 列表进一步限制源 IP,避免公网部署被任意 IP 伪造回调。
9.3 平台调用流媒体 REST API 一览
| 用途 | 触发场景 |
|---|---|
| 动态开 RTP 收流端口 | 启动直播 / 回放 |
| 关 RTP 收流端口 | 停止流 / CLOSE_PENDING 重试 |
| 抓取关键帧 jpeg | 触发抓图 |
| 开启 MP4 录制 | 录像下载 / 录像计划 |
| 停止录制 | 同上结束阶段 |
| 检查流就绪 | 抓图 / 录像计划等待流就绪的二次校验 |
十、协议消息覆盖
| # | 消息 | 方向 | 规范要求 | 是否实现 |
|---|---|---|---|---|
| 1 | REGISTER + Digest | 设备→平台 | 强制 | ✅ |
| 2 | MESSAGE Keepalive | 设备→平台 | 强制 | ✅ |
| 3 | MESSAGE Catalog Q/R/N | 双向 | 强制 | ✅ |
| 4 | MESSAGE RecordInfo Q/R | 双向 | 强制 | ✅ |
| 5 | MESSAGE Alarm Notify | 设备→平台 | 强制 | ✅ |
| 6 | INVITE / ACK / BYE(Play / Playback / Download) | 双向 | 强制 | ✅(Download 带 a=downloadspeed 加速) |
| 7 | INFO MANSRTSP(PLAY/PAUSE/SCALE/SEEK) | 平台→设备 | 强制 | ✅ |
| 8 | MESSAGE DeviceControl PTZ | 平台→设备 | 强制 | ✅ |
| 9 | MESSAGE DeviceControl TeleBoot | 平台→设备 | 强制 | ✅ |
| 10 | MESSAGE DeviceControl RecordCmd | 平台→设备 | 强制 | ✅ |
| 11 | MESSAGE DeviceInfo Q/R | 双向 | 强制 | ✅ |
| 12 | MESSAGE DeviceStatus Q/R | 双向 | 强制 | ✅ |
| 13 | MESSAGE ConfigDownload Q/R | 双向 | 强制 | ✅ |
| 14 | MESSAGE DeviceConfig Set(校时) | 平台→设备 | 强制 | ✅(UTC+8 强制) |
| 15 | MESSAGE PresetQuery Q/R | 双向 | 推荐 | ✅ |
| 16 | SUBSCRIBE Event=Catalog + NOTIFY | 双向 | 推荐 | ✅ |
| 17 | SUBSCRIBE Event=Alarm + NOTIFY | 双向 | 推荐 | ✅ |
| 18 | SUBSCRIBE Event=MobilePosition + NOTIFY | 双向 | 推荐 | ✅(可配置兼容 presence) |
| 19 | 级联 REGISTER + Keepalive(作为下级) | 双向 | 推荐 | ✅(qop=auth + Call-ID 复用) |
| 20 | 级联 Catalog 响应上级 Query | 平台→上级 | 推荐 | ✅(分批) |
| 21 | 级联响应上级 INVITE 被点播 + 反向 RTP | 双向 | 推荐 | ✅(三路收敛闭环) |
| 22 | 级联响应上级 SUBSCRIBE | 双向 | 推荐 | ✅ |
| 23 | 级联转发上级 Control 报文给下级 | 上级→平台→下级 | 推荐 | ✅ |
