MiBee NVR GB/T 28181 指南
本指南介绍 MiBee NVR 的 GB/T 28181(中国视频监控国家标准)集成:SIP 平台配置、设备接入、音频、语音对讲、订阅推送、PTZ、设备录像回放和故障排除。
什么是 GB/T 28181?
GB/T 28181 是中国视频监控网络系统的国家标准,定义了 IP 摄像机、NVR 和平台通过 SIP 和 RTP/PS 通信的方式。MiBee NVR 实现平台角色(UAS — 应答方),这意味着:
- 设备通过 SIP(UDP 端口 5060,默认)REGISTER 到 NVR
- 设备发送 Keepalive 心跳维持在线状态
- NVR INVITE 通道拉取 RTP/PS 媒体流(拉流模式)
- NVR 将 MPEG-PS 解复用为 H.264/H.265 NALU 与音频帧(G.711/AAC),进入标准录像/直播管线
兼容矩阵:GB/T 28181-2007/2011/2016/2022(见 internal/gb28181/doc.go)。支持的摄像机品牌包括海康威视、大华、宇视和其它 GB28181 兼容制造商。
快速开始
步骤 1:启用 GB28181 服务器
推荐:Web 设置页。打开 NVR Web UI → 设置 → GB28181,打开启用开关并填写参数后保存(密码为只写字段,留空保存表示保持不变)。

等价的 YAML 配置(mibee-nvr.yaml):
gb28181:
enabled: true
sip_listen: ":5060"
server_id: "34020000002000000001"
realm: "3402000000"
password: "yourpassword"
port_range: "30000-30050"
heartbeat_interval: "60s"
catalog_interval: "30m"
media_transport: "tcp-passive" # udp | tcp-passive | tcp-active(默认 tcp-passive,见下)
subscribe_catalog: true # 通道变更实时推送
subscribe_alarm: true # 报警订阅
subscribe_mobile_position: false
subscribe_expires: "3600s"
allowed_device_ids: [] # 空 = 允许所有设备注册(启动时会打印 WARN 提示;生产建议显式列出)
关键参数:
server_id:NVR 的 20 位 GB/T 28181 平台编号(设备端需完全一致)realm:SIP 摘要认证域(通常为 10 位区域码)password:SIP 摘要认证密码。留空 = 不鉴权(任何能访问 5060 端口的设备都可注册,见"安全考虑")media_transport:RTP 媒体传输 ——tcp-passive(默认,NVR 监听、设备连接,海康/大华 NAT 默认)、udp、tcp-active(NVR 拨向设备应答地址)。默认使用 TCP 的原因(#460):实测 UDP 媒体在真实 GB 相机上丢帧率约 16%(IDR 突发包触发网卡/软中断路径丢包,每次丢帧打断 P 帧参考链,表现为花屏/马赛克直到下个 IDR);同一网络 TCP 丢帧 <1%。个别不支持 TCP 媒体的老设备可改回udp。
步骤 2:配置摄像机
在 GB28181 摄像机(海康、大华等)上配置 SIP 平台接入:
海康威视(Web UI):网络 → 高级平台接入 —— 服务器地址填 NVR IP、服务器端口 5060、设备 ID 填 20 位国标码、密码与 NVR 一致、启用平台接入。
大华(Web UI):网络 → TCP/IP → 28181 —— 服务器 IP/端口/设备 ID/设备域(realm)/密码与 NVR 一致、启用 28181。
设备应在几秒内 REGISTER 成功。
步骤 3:自动入册(零手动配置)
无需手动添加相机。 设备注册成功后 NVR 自动完成:
- 记入设备列表并跟踪在线状态(心跳超时判离线)
- 自动查询目录(Catalog),发现全部真实视频通道(组织节点自动跳过)
- 每个通道自动创建一台相机(
gb-<通道ID>),与 ONVIF/RTSP 相机并列出现在相机列表 - 自动 INVITE 拉流开始录像
- 自动补全厂商/型号(DeviceInfo),订阅目录变更与报警推送
需要手动绑定特殊通道时,也可以用 YAML 或 Web 表单显式创建:
cameras:
- id: "hikvision-front-door"
name: "海康前门"
protocol: "gb28181"
gb28181:
device_id: "34020000001320000001"
channel_id: "34020000001320000001"
recording_enabled: true
enabled: true
步骤 4:开启音频(按相机)
音频默认关闭。在相机编辑页打开 音频 开关(或 API PUT /api/cameras/{id} {"audio_enabled": true})后,PS 流中的音频轨(G.711 A-law/μ-law、AAC)会写入 MP4 音轨并进入直播音频。
功能总览
| 能力 | 状态 | 说明 |
|---|---|---|
| REGISTER + Digest 鉴权 / 白名单 | ✅ | 401 挑战、周期重注册、注销、IP 变化自动重建会话 |
| 自动入册 | ✅ | 注册 → 目录 → 通道建卡 → 自动拉流,零手动配置 |
| 实时点播(INVITE) | ✅ | UDP / TCP 被动 / TCP 主动(0x24、rfc4571、auto 组帧) |
| 录像 | ✅ | H.264/H.265,30s 分片、IDR 对齐、滚动合并 |
| 直播 | ✅ | 经 StreamHub 进 HLS/WebRTC/FLV/WS 全部协议 |
| 音频 | ✅ | G.711 A-law/μ-law + AAC → MP4 音轨 + 直播音频;无 PSM 流自动兜底 |
| 语音对讲 | ✅ | 浏览器麦克风 → 设备扬声器(LiveView 一键对讲) |
| 设备录像检索/回放 | ✅ | RecordInfo + 回放取流进录像库(Recordings 页)+ 倍速/拖动 |
| PTZ + 预置位 | ✅ | 方向/变倍/预置位/巡航(FICommand) |
| 目录订阅 | ✅ | 通道变更实时 NOTIFY,替代纯轮询 |
| 报警订阅 | ✅ | → 事件总线/SSE/REST 环形缓存 |
| 移动位置订阅 | ✅ | 车载/布控球场景,REST 查询轨迹 |
| 时钟同步 | ✅ | 设备发 Query,平台应答标准时间 |
| 设备信息/状态自动化 | ✅ | 厂商/型号自动补全,keepalive 不丢元数据 |
| 多级级联(下级角色) | ✅ | 向上级平台注册、聚合目录、INVITE 转发(见"级联上联") |
| GB35114 国密 | ⏸ | 按需评估(见 #341) |
配置参考
服务器配置
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
enabled |
bool | false |
启用 GB28181 服务器 |
sip_listen |
string | ":5060" |
SIP UDP 监听地址 |
server_id |
string | (必填) | 平台 20 位国标编号 |
realm |
string | (必填) | SIP 摘要认证域 |
password |
string | (建议设置) | SIP 摘要认证密码;留空 = 不鉴权 |
port_range |
string | "30000-30050" |
RTP 媒体端口池("start-end") |
heartbeat_interval |
string | "60s" |
期望的设备心跳间隔 |
catalog_interval |
string | "30m" |
目录轮询间隔(订阅开启时仅作兜底) |
media_transport |
string | "tcp-passive" |
媒体传输:tcp-passive / udp / tcp-active(默认 TCP 的原因见上文,#460) |
sip_transport |
string | "udp" |
信令传输:udp(可叠加 tcp 监听) |
tcp_framing |
string | "auto" |
TCP 组帧:"rfc4571"、"0x24"、"auto" |
subscribe_catalog |
bool | true |
目录订阅(通道变更实时推送) |
subscribe_alarm |
bool | true |
报警订阅 |
subscribe_mobile_position |
bool | false |
移动位置订阅(静止相机无需开启) |
subscribe_expires |
string | "3600s" |
订阅有效期(80% 时自动续订) |
allowed_device_ids |
[]string |
[] |
注册白名单(空 = 允许所有) |
allow_same_ip_enroll |
bool | false |
允许同 IP 双协议并存:即使已有相机从该设备 IP 取流(或 ONVIF 序列号匹配),GB28181 通道仍自动建条目。适用于刻意让 ONVIF + GB28181 并存的场景,#596 |
sub_channel_probe |
string | "auto" |
子通道探测模式:auto(仅探测厂商为海康/大华的设备)/ on(探测所有设备)/ off(关闭),#560 |
sub_channel_probe_offset |
int | 1 |
子通道候选码 = 主通道码 + 该偏移(海康惯例 +1;0 = 禁用探测),范围 0–99 |
alarm_linkage |
object | {enabled: false} |
报警联动流(#355):{enabled, duration}——收到报警通知时,对未在推流的报警通道发起 INVITE,保持 duration(默认 "60s")后 BYE;该通道对应的相机要求录像时则保持不断开 |
security35114 |
object | {enabled: false} |
GB35114 国密安全(SM2/SM3 证书体系)——见下文 GB35114 安全增强;仅在 -tags gb35114 构建的二进制中生效,默认构建启用时仅告警 |
tcp_mode(bool)是media_transport的旧别名,保留仅为 YAML 兼容,已不再影响默认值(v0.12.0 起默认即tcp-passive,#460);需要 UDP 请显式设置media_transport: "udp"。
GB35114 安全增强
gb28181.security35114 节(#714/#707,GB35114 A 级)启用国密证书体系:REGISTER 双向认证 + keyed-SM3 Note 完整性。仅在 -tags gb35114 构建的二进制中生效;默认构建下启用该节只记录一条警告。Digest 认证(password)设备与国密路径并存、互不干扰。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
enabled |
bool | false |
启用 GB35114 REGISTER 认证器 |
platform_cert |
string | (必填) | 平台 SM2 签名证书路径(双向挑战时用它签名) |
platform_key |
string | (必填) | 平台 SM2 私钥路径 |
device_certs_dir |
string | 空 | 预置设备证书目录,每设备一个 <deviceID>.pem 文件。可选——设备也可通过 Capability cnonce 上报证书(信任首用);预置是更严格的策略 |
试点证书签发(无 CA 的实验/小型部署):-tags gb35114 构建附带一条签发命令——
mibee-nvr gen-gb35114-certs --platform-id <20位平台ID> --device-id <20位设备ID>[,<20位设备ID>...] --out-dir gb35114-certs
自签 SM2 平台身份 + 由平台签发的设备身份(PKCS#8 私钥 0600 + GM/T 0015-2012 证书),输出布局即上表三个路径参数的取值形态(devices/<deviceID>.pem),把设备证书与私钥分发到对应设备即可。签发材料经完整的 Challenge/VerifyRegister/VerifyOK 握手回归验证(两侧 VKEK 一致)。生产部署请改用真实 CA(CFCA 等)签发。
相机配置
| 参数 | 类型 | 描述 |
|---|---|---|
protocol |
string | 必须为 "gb28181" |
gb28181.device_id |
string | 设备 20 位国标编码 |
gb28181.channel_id |
string | 通道 20 位国标编码 |
audio_enabled |
bool | 音频开关(默认 false,开启后录 MP4 音轨 + 直播音频) |
gb28181.sub_channel_id |
string | 探测到的子码流通道编码(自动回填,fill-once;清空后重启可重新探测)。有值时 ?quality=sub 与子流转发可用,#560 |
子码流(子通道探测,#560)
GB 设备的子码流通常不在目录里——海康系设备按通道编码偏移(主码流码 +1)隐式存在。NVR 在设备入册并稳定取流后,按厂商惯例对每个已绑定相机的主通道做一次子通道探测(一次额外 INVITE,进程生命周期内最多一次):
- 成功(子通道有媒体流):探测码自动落
gb28181.sub_channel_id(fill-once),/api/cameras/{id}/protocols如实回报sub_stream.available=true,?quality=sub(WS/FLV/HLS/WHEP 宫格与级联子流转发)即可用 - 失败(404/超时/486):静默放弃,相机保持无子流的降级路径,零错误状态
- 偏移量可配(
sub_channel_probe_offset,默认 1);auto模式只对 DeviceInfo 厂商为海康(Hikvision/海康)/大华(Dahua/大华)的设备探测,自研设备零打扰 - 已回填的
sub_channel_id不会被覆盖;清空该字段并重启 NVR 可重新触发探测 - 目录里已存在的兄弟通道码(如多通道 NVR 的 02/03)绝不会被当作子码流复用
音频
- 编解码:G.711 A-law / μ-law(8kHz)、AAC(ADTS 封装自动转 ASC)
- 开关:按相机
audio_enabled,关闭时丢弃解复用出的音频帧 - 无 PSM 流兜底:部分固件把音频复用进 PS 流但不发 PSM(或 PSM 不声明音频)。NVR 按优先级判定编解码:PSM 声明 → INVITE 应答 SDP
a=rtpmap→ 字节启发式(ADTS 同步字 → AAC;μ/A-law 按静音簇投票,4KB 内静音样本 μ-law 聚 0xFF/0x7F、A-law 聚 0x55/0xD5)。判定时记 INFO 日志codec inferred - 无 PTS 音频:按样本数推进时间线,兼容省略音频 PTS 的固件
- 设备端接入要求(推荐做法):音频复用进同一路 PS/RTP 流(同端口同 SSRC),PSM 声明音频(stream_type 0x90=μ-law / 0x91=A-law / 0x0F=AAC,stream_id 0xC0-0xDF),G.711 发 8kHz 单声道裸字节
语音对讲
LiveView 页国标相机有 对讲 按钮:浏览器麦克风 → AudioWorklet 降采样到 8kHz → A-law 编码 → WebSocket 上行 → NVR 发起 audio-only INVITE(m=audio ... RTP/AVP 8,a=sendrecv)→ 设备接收地址收 RTP。半双工:直播音频与对讲下行并存。
API:GET /api/cameras/{id}/gb28181/talk(WebSocket,二进制帧 = A-law 字节)、GET /api/cameras/{id}/gb28181/talk/status。
级联上联(下级角色)
NVR 可作为下级平台向上级 GB/T 28181 平台上联:本机相机聚合为国标目录上报,上级 INVITE 任意通道时以 RTP/PS 转发媒体(纯封装不转码)。上级无需特殊支持——任何标准平台(包括另一台 MiBee NVR 的平台角色)即可对接。
gb28181_cascade:
enabled: true
server_domain: "34020000002000000001" # 上级平台 20 位编号
server_addr: "192.168.1.10:5060" # 上级 SIP 地址
local_device_id: "34020000001320000099" # 本 NVR 作为下级设备的编号
realm: "3402000000"
password: "..." # encrypt-config 加密
sip_listen: ":5061" # 级联信令端口(与平台角色 5060 并存)
heartbeat_interval: "60s"
register_expires: 3600
hub_activation_timeout: "10s" # 多级级联:上级点播未在录 GB 子相机的按需激活限时(#451)
行为要点:
- 通道编号按相机首次入目录顺序分配(
<编号前10位>132+7位序号),持久化防重启变号——上级的绑定始终有效 - REGISTER + Digest、Expires 80% 续注、Keepalive;上级重启(keepalive 403)立即重注册
- 目录应答聚合全部非 MJPEG 相机;H.264/H.265 由首帧 NAL 嗅探决定 PSM 类型
- 上级 INVITE → 200 OK(sendonly) → 从 StreamHub 取流 → PS 复用 → RTP 推送;BYE/错误清理
- 目录收敛(
cameras[].cascade_enabled: false):该相机从聚合目录隐藏、对其通道的 INVITE 返回 404,但通道编码分配保留——重新开启即恢复原编码,上级绑定不漂移 - 级联上报子码流(
cameras[].cascade_sub_stream: true):INVITE 转发改走相机按需拉取的子码流——低分辨率档让上级预览不再吃满上行带宽;相机无子码流或拉取失败自动回退主流,无子码流的相机不受影响 - 多级级联按需激活(
gb28181_cascade.hub_activation_timeout,#451):上级点播一个当前未在录的 GB 子设备通道时,中间级先向该子设备发起本地 INVITE(限时默认 10s),拿到流再转发——超时回 500 不建立无媒体对话,BYE 后按空闲回收本地拉流;已激活引用随会话释放。非 GB 相机不走此路径 - 多上级上联(
gb28181_cascade.upstreams,#370):单上级表单之外可配置任意数量的额外上级——每条独立运行自己的 REGISTER/Keepalive 会话(共享 SIP 监听端口),独立在线状态;字段留空回退单上级表单值 - v1 限制:仅视频(hub 音频暂不区分 G.711 A/μ 律);不推送目录变更 NOTIFY(上级轮询兜底)
多上级配置示例:
gb28181_cascade:
enabled: true
server_domain: "34020000002000000001" # 首个上级(单上级表单仍是第一个 upstream)
server_addr: "192.168.1.10:5060"
local_device_id: "34020000001320000099"
realm: "3402000000"
password: "..."
upstreams: # 额外上级(#370)
- server_domain: "34020000002000000002"
server_addr: "192.168.1.11:5060"
local_device_id: "34020000001320000098" # 该平台分配给本机的编号(可各不相同)
realm: "3402000000"
password: "..."
heartbeat_interval: "60s" # 可选:覆盖该上级的保活节奏
register_expires: 3600 # 可选:覆盖该上级的 REGISTER 有效期
订阅与事件
- 目录订阅:设备通道变更通过 NOTIFY 实时推送(合并进通道表并自动建卡)
- 报警订阅:
GET /api/gb28181/devices/{id}/alarms查询环形缓存(最近 200 条),同时进事件总线(SSEgb28181.alarm) - 移动位置订阅:
GET /api/gb28181/devices/{id}/positions查询位置轨迹 - 三个开关与有效期见设置页 / 上表;到期前 80% 自动续订
设备录像检索与回放
Recordings 页可按国标通道检索设备侧存储的录像(RecordInfo)并取回:取回片段经正常录像管线落盘(分段、记录行),在 Recordings 页直接播放,支持倍速/拖动(INFO 控制)。
API:
GET /api/gb28181/channels/{id}/records?start=&end=— 检索设备录像列表POST /api/gb28181/channels/{id}/playback— 开始取回(body 含 start/end)GET /api/gb28181/channels/{id}/playback— 取回进度DELETE /api/gb28181/channels/{id}/playback— 停止POST /api/gb28181/channels/{id}/playback/control— 倍速/拖动/暂停
PTZ 控制
PTZ 经 MANSCDP DeviceControl 下发。支持方向(含对角)、变倍(需 PTZType=2)、预置位/巡航(FICommand)。通道的 PTZType 来自目录报告(0=无、1=云台、2=云台+变倍)。
Web UI:LiveView 相机页 PTZ 面板(按住移动、松开停止、预置位调用/设置)。
curl -X POST http://localhost:9090/api/gb28181/channels/34020000001320000001/ptz \
-H "Content-Type: application/json" \
-H "Authorization: Basic base64(username:password)" \
-d '{"direction": "up", "speed": 128}'
方向:up/down/left/right/up-left/up-right/down-left/down-right/zoom-in/zoom-out/stop。
API 参考
设备与通道
GET /api/gb28181/devices— 已注册设备(支持 ETag)GET /api/gb28181/devices/{id}/channels— 设备通道列表POST /api/gb28181/devices/{id}/catalog-refresh— 触发目录刷新(202)GET /api/gb28181/devices/{id}/alarms— 报警环形缓存GET /api/gb28181/devices/{id}/positions— 移动位置轨迹
媒体会话
POST /api/gb28181/channels/{id}/invite/bye— 手动拉流/停流POST /api/gb28181/channels/{id}/ptz— PTZ 控制
按需抓拍与手动录像(GB/T 28181-2022)
POST /api/gb28181/channels/{id}/snapshot— 向设备下发 SnapShotCmd 按需抓拍({"snap_num":1,"interval":0});设备把 JPEG 回传到公共回调端点POST /api/gb28181/snapshot/upload?session=<SessionID>,帧保存至snapshots/gb-<通道ID>/并触发camera.snapshot事件;会话在收到设备完成通知后关闭,超时未收到通知则判为失败POST /api/gb28181/channels/{id}/record— 手动开始 / 停止录像({"action":"start"}/{"action":"stop"},对应 RecordCmd)
录像检索/回放(设备侧)
- 见上节
语音对讲
GET /api/cameras/{id}/gb28181/talk(WebSocket)、GET .../talk/status
错误响应
| 状态 | 场景 |
|---|---|
| 400 | 请求体缺失/畸形;不支持的 PTZ |
| 404 | 通道不存在 |
| 409 | 设备离线 |
| 500 | 内部错误(MANSCDP 编码/发送失败) |
故障排除
设备未注册
- 确认
sip_listen监听(ss -ulnp | grep 5060)与防火墙放行 UDP 5060 - 核对设备端五要素:服务器 IP/端口 5060/服务器 ID(须与
server_id完全一致)/域(realm)/密码 - 看日志:
journalctl -u mibee-nvr -f | grep -i gb28181——REGISTER auth failed= 密码不匹配;not in allowlist= 白名单 - 改过 NVR 密码后:设备下一次重注册(≤1 个注册周期)会 403 掉线,设备端同步修改后自动恢复,无需重新入册
视频黑屏 / 无流
- 检查
port_range未耗尽、防火墙放行该 UDP 段 - NAT 场景切换
media_transport: tcp-passive - TCP 组帧报错时依次尝试
tcp_framing: rfc4571 / 0x24 / auto - 编码:H.264/H.265 自动探测,无需配置
花屏 / 马赛克(图像下半截模糊有码)
典型症状:画面某区域(常见下半屏)出现马赛克/色块,数秒后随下一个关键帧恢复,周而复始。根因是 UDP 媒体丢帧(IDR 突发包触发丢包 → P 帧参考链断裂,#460 实测丢帧率可达 16%):
- 确认
media_transport为默认的tcp-passive(若曾被改为udp请改回) - 已是 TCP 仍花屏 → 检查
tcp_framing(依次尝试rfc4571/0x24/auto) - 服务器端可对照接收日志中的
gap_skipped/AU ended mid-PES计数定位丢包位置
音频无声
- 确认相机 音频开关 已开启(
audio_enabled,默认关) - 看日志
codec inferred—— 无 PSM 设备会自动判定编解码;若始终无此日志且无音轨,抓包确认设备确实把音频复用进了 PS 流 - 设备端推荐做法见"音频"节;无 PSM 也能出声(自动兜底),但其它平台(ZLMediaKit 等)会丢,建议设备侧补 PSM 声明
会话周期性回收重邀
日志出现 recycling stale session reason=no keyframe 且录像每隔约一分多钟有空窗:设备关键帧间隔(GOP)超过 NVR 的 75 秒看门狗。属正常自愈行为(重邀强制出新 IDR),但建议把设备 GOP 收敛到 2-4 秒。
REGISTER 源端口轮换
部分 SIP 栈每个 REGISTER 换源端口。NVR 仅按 IP 判断地址变化,端口轮换不会回收会话,无需处理。
心跳超时掉线
设备心跳间隔与 NVR heartbeat_interval(默认 60s)不匹配时调整任一侧。
字符集乱码(GBK vs UTF-8)
MANSCDP 编解码器自动处理:剥离 XML 声明、UTF-8 校验、GB18030/GBK 回退。仍乱码时检查设备端编码设置。
时钟同步
设备因时钟漂移鉴权异常或录像检索时间不对时:NVR 自动应答设备的 TimeSync 查询;两侧建议均同步 NTP。
限制与已知问题
- 设备自注册伪通道:NVR 重启后,多通道目录设备会短暂出现一台"设备自身通道"的相机(不推流)。已知问题,重启后手动归档即可,跟踪于 #352
- 对讲真机覆盖:语音对讲目前经模拟器 E2E 验证,真机回环验证跟踪于 #353
- TCP 0x24 组帧:非标准扩展(GB/T 28181-2016/2022 指定 RFC4571),混合部署用
auto - 多级级联 / GB35114:未实现,按需评估(#341)
- 报警联动点播:报警事件已进总线,联动自动拉流跟踪于 #355
安全考虑
- 鉴权:务必设置
password(留空 = 任何可达设备都能注册)。配合allowed_device_ids白名单双层防护 - 传输:SIP/RTP 为明文(GB35114 国密/TLS 未实现)。公网部署必须用防火墙/VPN 收敛暴露面,勿直接暴露 5060 与端口池
- 端口池:默认 51 路,按并发需求扩展(RPi 3B 建议 <200)
支持资源
- 快速开始 · 配置指南 · API 参考
- GB/T 28181-2016 / 2022 国家标准文本
- GitHub Issues · Discussions