Featured image of post GB28181 视频监控平台深度剖析:WVP-GB28181-pro 全链路源码分析

GB28181 视频监控平台深度剖析:WVP-GB28181-pro 全链路源码分析

WVP-GB28181-pro 视频监控平台核心组件与完整调用链分析:SipLayer 服务端、SipProvider 信令处理、SIPRequestProcessor 请求分发、设备注册链路、目录查询流程

WVP-GB28181-pro 是国内基于 GB/T 28181 国标协议的视频监控管理平台,2020 年 GitHub 上 648540858/wvp-GB28181-pro 仓库 star 数已经超过 4k。它的核心是用 JAIN SIP 协议栈做信令服务,把 GB28181 设备(摄像头、NVR、平台)注册到平台,然后做实时视频流转发、云端录像、录像回放、级联、报警等。本文从源码层做一次完整剖析。

本文写于 2020 年 9 月——WVP-GB28181-pro 1.x 时代。该项目至今仍在持续迭代。

一、GB28181 协议基础

GB/T 28181-2016《安全防范视频监控联网系统信息传输、交换、控制技术要求》是中国公安部主导的国标协议,用于把不同厂商的摄像头/NVR 统一接入到一个平台上

1.1 协议核心特征

  • 信令协议:SIP(RFC 3261)+ SDP
  • 传输层:UDP(默认)/ TCP
  • 媒体流:RTP/RTCP(基于 RTSP 推流或 PS 封装的 RTP)
  • 编解码:H.264 / H.265 / SVAC
  • 核心交互:注册、目录查询、实时点播、回放、下载、报警、级联

1.2 GB28181 与 ONVIF 的区别

维度GB28181ONVIF
国别中国国标国际标准
协议SIPHTTP + RTSP
推送方式主动注册 + 平台调度设备发现 + RTSP 拉流
主要场景平安城市、雪亮工程企业园区、商业楼宇
厂商支持海康/大华/宇视/科达Axis/Bosch/Hanwha

二、WVP-GB28181-pro 项目架构

2.1 项目定位

WVP-GB28181-pro 是纯 Java 实现的 GB28181 国标信令网关 + 流媒体服务

  • 前端:Vue + Element UI(管理摄像头、用户、回放、录像)
  • 后端:Spring Boot + JAIN SIP + ZLMediaKit(流媒体)
  • 存储:MySQL(设备信息)+ Redis(信令缓存)+ MinIO/阿里 OSS(录像)

2.2 核心模块

1
2
3
4
5
6
7
com.<your-org>.stream.gb28181
├── SipLayer              # SIP 服务端(监听 5060 端口)
├── config                # 配置(信令端口、IP、上级平台)
├── media                 # 媒体流转发
├── session               # 客户端会话管理
├── event                 # 事件订阅与通知
└── controller            # REST API(前端调用)

2.3 关键依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
    <!-- SIP 协议栈 -->
    <dependency>
        <groupId>javax.sip</groupId>
        <artifactId>jain-sip-ri</artifactId>
        <version>1.3.0-91</version>
    </dependency>

    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- ZLMediaKit Java SDK -->
    <dependency>
        <groupId>com.aizuda</groupId>
        <artifactId>zlmediakit-java-sdk</artifactId>
    </dependency>
</dependencies>

三、SIP 信令栈核心:JAIN SIP API

3.1 SipProvider 实现

WVP 使用的 JAIN SIP 协议栈在 gov.nist.javax.sip 包下:

1
2
3
4
5
6
public class SipProviderImpl implements
        SipProvider,           // 公共 SIP 接口
        SipProviderExt,        // 扩展接口
        SIPTransactionEventListener,  // 事务事件
        SIPDialogEventListener {     // 对话事件
}

三个核心能力

  1. 发送 SIP 消息(REGISTER / INVITE / MESSAGE / BYE)
  2. 接收 SIP 消息(响应 + 异步事件)
  3. 管理 SIP 事务 + 对话(事务超时、重传)

3.2 SipListener 接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public interface SipListener extends EventListener {
    // 1. SIP 请求消息到达时  REGISTER/INVITE/BYE/MESSAGE
    void processRequest(RequestEvent event);

    // 2. SIP 响应消息到达时(200 OK / 401 / 403 等)
    void processResponse(ResponseEvent event);

    // 3. SIP 事务超时(INVITE 超时、OPTIONS 心跳超时等)
    void processTimeout(TimeoutEvent event);

    // 4. 网络 I/O 异常(连接断开、发送失败)
    void processIOException(IOExceptionEvent event);

    // 5. SIP 事务结束(ACK 收到后 INVITE 事务终结)
    void processTransactionTerminated(TransactionTerminatedEvent event);

    // 6. SIP 对话(Dialog)结束(双方会话完全终结)
    void processDialogTerminated(DialogTerminatedEvent event);
}

WVP 中所有 SIP 入口都通过 SipListener 接收,然后分发给具体的 ISIPProcessorObserver 处理。

四、SipLayer 服务端源码剖析

4.1 SipLayer 完整结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Slf4j
@Component
@Order(value = 10)
public class SipLayer implements CommandLineRunner {
    @Autowired
    private SipConfig sipConfig;

    @Autowired
    private ISIPProcessorObserver sipProcessorObserver;

    @Autowired
    private UserSetting userSetting;

    // TCP 与 UDP 的 SIP Provider 映射
    private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
    private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();

    // 已监听过的 IP(防止重复 bind)
    private final List<String> monitorIps = new ArrayList<>();

    @Override
    public void run(String... args) {
        // 应用启动时初始化 SIP 监听
        initSipServer();
    }

    public SipProviderImpl getUdpSipProvider(String ip) { /* ... */ }
    public SipProviderImpl getUdpSipProvider() { /* ... */ }
    public SipProviderImpl getTcpSipProvider(String ip) { /* ... */ }
    public SipProviderImpl getTcpSipProvider() { /* ... */ }
    public String getLocalIp(String deviceLocalIp) { /* ... */ }
}

4.2 关键设计点

1. 双协议监听(TCP/UDP)

  • GB28181 设备通常用 UDP 5060 端口
  • 高级设备或跨网段用 TCP 5060 端口
  • 同一进程需要同时维护两套 SipProvider

2. 多 IP 监听

  • 多网卡服务器需要监听所有 IP
  • tcpSipProviderMap / udpSipProviderMap 按 IP 维度维护
  • monitorIps 列表去重,防止重复 bind

3. 启动顺序 @Order(10)

  • Spring Boot CommandLineRunner 启动后立即初始化
  • @Order(10) 保证在 Spring 主流程就绪后才启动 SIP
  • 失败的 SIP 初始化不会阻断 Web 服务

五、完整调用链:设备注册到目录查询

5.1 时序图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  Device    WVP Controller    sipCommander    设备    CatalogResponseMessageHandler    DeviceChannelMapper    DB
    │           │                 │            │                  │                      │              │
    │─注册成功─▶│                 │            │                  │                      │              │
    │           │─sync(device)───▶│            │                  │                      │              │
    │           │                 │─CatalogQuery─▶│                │                      │              │
    │           │                 │◀──Catalog XML─│                │                      │              │
    │           │                 │            │──handle()───────▶│                      │              │
    │           │                 │            │                  │──batchAdd───────────▶│              │
    │           │                 │            │                  │──batchUpdate────────▶│              │
    │           │                 │            │                  │──batchDel───────────▶│              │

5.2 调用链详解

阶段 1:设备注册

1
2
3
4
5
6
设备 → REGISTER → SipLayer(UDP 5060)
                 → SipListener.processRequest()
                 → ISIPRequestObserver(注册处理器)
                 → 校验设备 ID + 密码
                 → 更新设备状态为"在线"
                 → 200 OK

阶段 2:心跳保活

1
2
3
4
5
设备 → MESSAGE(Keepalive) → SipLayer
                            → SipListener.processRequest()
                            → 解析 XML 设备状态
                            → 更新设备最后心跳时间
                            → 200 OK

阶段 3:目录查询(Catalog Query)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
WVP Controller 触发"同步通道"
  → DeviceService.sync()
  → sipCommander.catalogQuery(device, deviceChannel)
  → SIP MESSAGE(带 Catalog 查询 XML)
  → 设备 → 200 OK
  → 设备 → SIP MESSAGE(异步返回 Catalog 列表)
  → SipLayer → CatalogResponseMessageHandler.handle()
  → 解析 XML 中的通道列表
  → DeviceChannelMapper.batchAdd(新增通道)
  → DeviceChannelMapper.batchUpdate(更新通道)
  → DeviceChannelMapper.batchDel(删除通道)
  → 写入 DB

六、请求处理统一入口:ISIPRequestProcessor

6.1 处理器接口

1
2
3
4
5
6
7
public interface ISIPRequestProcessor {
    // 处理方法名
    String getMethod();

    // 处理逻辑
    void process(RequestEvent event);
}

6.2 内置处理器

WVP 内部为每种 SIP 请求都实现了一个 ISIPRequestProcessor

Method处理器用途
REGISTERRegisterRequestProcessor设备注册
MESSAGEMessageRequestProcessor消息分发(心跳/目录/报警)
INVITEInviteRequestProcessor实时点播
BYEByeRequestProcessor结束点播
SUBSCRIBESubscribeRequestProcessor事件订阅
ACKAckRequestProcessorINVITE 确认
OPTIONSOptionsRequestProcessor能力探测

6.3 派发器实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class SIPRequestProcessorParent implements SipListener {
    @Autowired
    private List<ISIPRequestProcessor> processors;  // Spring 自动注入

    @Override
    public void processRequest(RequestEvent event) {
        Request request = event.getRequest();
        String method = request.getMethod();

        for (ISIPRequestProcessor processor : processors) {
            if (method.equals(processor.getMethod())) {
                processor.process(event);
                break;
            }
        }
    }
}

设计模式策略模式 + 依赖注入——新增请求类型只需要新增一个 ISIPRequestProcessor 实现,Spring 自动扫描注册。

七、流媒体集成:ZLMediaKit

WVP 本身不做媒体流转发,它把流媒体的工作交给 ZLMediaKit(一个基于 C++ 的高性能流媒体服务):

1
2
3
GB28181 设备 → RTP/PS 流 → WVP 接收 → ZLMediaKit 拉流
                                       → 转 RTMP/HLS/WebRTC
                                       → 推到客户端

7.1 ZLMediaKit 角色

  • 接收端:通过 RTP 接收 PS 流(来自 GB28181 设备)
  • 转换端:把 PS 流转换为 RTMP/HLS/WebRTC
  • 分发端:把转换后的流推给浏览器/移动端/录像

7.2 WVP 调用 ZLMediaKit 的方式

1
2
3
4
5
6
7
8
// WVP 通过 HTTP API 调用 ZLMediaKit
POST http://zlmediakit:9000/index/api/openRtpServer
Body:
{
  "port": 10000,
  "enable_tcp": true,
  "stream_id": "channel_001"
}

八、关键坑点与实战经验

8.1 SIP 端口冲突

1
2
3
4
# 错误:Address already in use
# 原因:5060 端口被系统 SIP 服务占用
lsof -i :5060
# 解决:修改 WVP 配置改用其他端口

8.2 设备注册失败

现象原因解决
401 Unauthorized设备密码错误检查 UserSetting 配置
408 Request Timeout网络不通检查防火墙 + 端口
480 Temporarily Unavailable平台未就绪检查 ZLMediaKit 状态

8.3 视频流拉不到

现象原因解决
ZLMediaKit 返回错误流地址配置错误检查 stream_id
客户端黑屏编解码不兼容强制转码
录像文件 0 字节录制路径权限chown 给 WVP 用户

九、写在最后

WVP-GB28181-pro 的成功在于:

  1. 选型准确——Java 做信令网关(生态成熟、Spring Boot 快速开发)
  2. 解耦清晰——SIP 信令 + 媒体流分离(ZLMediaKit 处理高吞吐)
  3. 实战性强——适配海康/大华/宇视主流厂商设备
  4. 社区活跃——issue 响应快,文档持续更新

个人建议

  • 想要自建视频监控平台:WVP + ZLMediaKit 是国内最成熟的组合
  • 商业项目:考虑EasyCVR / TSINGSEE 等商业产品(带 UI 和运维)
  • 国家级项目:需要支持GB28181-2022 新国标(WVP 已部分支持)

参考资料

十、2024+ 视角:GB28181-2022、AI 视频分析与 WebRTC 播放

本文写于 2020 年 9 月,WVP-GB28181-pro 至今仍是最活跃的国标信令网关。下面补充 2024-2026 行业关键变化:GB28181-2022 新国标、AI 视频分析、WebRTC 浏览器播放、ZLMediaKit 演进。

10.1 GB28181-2022 新国标:协议升级到"互联网友好"

GB/T 28181-2022 在 2023 年正式实施,对开发影响最大的是 4 件事

  1. TCP 协议从可选升级到推荐——2020 时代用 UDP 5060 是默认,2024+ 因为防火墙/NAT,TCP 已成为企业内部部署首选
  2. H.265/HEVC 强制支持——eladmin 之类的旧版本 WVP 客户端无法解码 H.265 流,2024+ WVP-GB28181-pro 默认带 H.265 解码
  3. 信令通道支持 HTTPS / WSS——2020 时代 SIP 走 UDP 明文,2024+ 公安部等保 2.0 三级要求信令加密
  4. 多级级联 + 跨域互联——上/下级平台鉴权从 IP 白名单升级到 OAuth 2.0

WVP-GB28181-pro 在 2024 年的 2.0+ 版本(社区称为 WVP-PRO v2)已经默认兼容 2016 + 2022 双协议。

10.2 WVP 项目的关键演进(2020 → 2026)

维度2020(v1.x)2024+(v2.x)
Spring Boot2.4.x3.2.x
JDK817 / 21
SIP 协议栈jain-sip-ri 1.3.0-91mjSIP 或 RestComm 替代(社区维护)
流媒体ZLMediaKit HTTP APIZLMediaKit 25.x + SRS 5.x 双支持
前端Vue 2 + Element UIVue 3 + TypeScript + Vben
协议支持GB28181-2016GB28181-2016 + 2022 双协议
AI 集成内置 AI 视频分析插件(火焰/安全帽/人脸)

10.3 AI 视频分析:从"看到"到"看懂"

2020 年的 WVP 主要是"信令 + 流转",2024-2026 的核心增量是 AI 视频分析

  • 海康/大华原生 AI 摄像头(内置 NPU)——边缘推理,云端只收告警
  • 云端 AI 分析插件(基于 YOLOv8 / RT-DETR)——WVP 接入 RTSP 流后调用 AI 服务,实现"事后分析 + 实时告警"
  • 多模态大模型(LLaVA、GPT-4V)——2025-2026 的 WVP 高级版本可以"上传一张图,问 AI 视频里发生了什么"

实战架构(2025 主流):

1
2
3
4
5
6
7
GB28181 摄像头 → WVP(信令)→ ZLMediaKit(流媒体)
                          AI 分析服务(Python + YOLOv8)
                          告警 → Kafka → 业务系统
                          录像 → MinIO / 阿里 OSS

单纯做信令网关的 WVP 价值在 2025 年正在被压缩,“WVP + ZLMediaKit + AI 分析"的三件套才是完整方案

10.4 WebRTC 浏览器播放:解决 H5 时代痛点

2020 年的痛点:浏览器只能看 HLS(延迟 3-5 秒)或 RTMP(需要 Flash)。2024+ 的方案

  • ZLMediaKit 内置 WebRTC——浏览器直接 <video> 标签播放,延迟 <500ms
  • WVP 把 GB28181 PS 流推到 ZLMediaKit → 转 WebRTC——完整链路延迟 <1s
  • WHEP / WHIP 协议——2024 年成为 WebRTC 与 GB28181 互通的事实标准

实际项目里:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 浏览器端 WebRTC 拉流(2024+ 主流)
const pc = new RTCPeerConnection();
pc.addTransceiver('video', { direction: 'sendrecv' });
pc.addTransceiver('audio', { direction: 'sendrecv' });

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// 拉 ZLMediaKit 的 WebRTC 流
const resp = await fetch('http://zlmediakit:9000/index/api/webrtc?app=live&stream=cam001&type=play');
const answer = await resp.json();
await pc.setRemoteDescription(answer);

pc.ontrack = (event) => {
  document.getElementById('video').srcObject = event.streams[0];
};

10.5 实战补充(2024-2026)

  1. K8s 部署:WVP + ZLMediaKit 全部跑在 K8s,VIP 改成 K8s Service(不再需要 Keepalived)
  2. 可观测性:WVP 接入 Prometheus + Grafana,SIP 注册成功率、在线设备数、流转发 QPS 全部可视化
  3. 安全加固
    • SIP 端口从 5060 改 5061(WSS 加密)
    • Redis 加 TLS
    • ZLMediaKit 的 HTTP API 加 JWT 鉴权
  4. 大规模部署:单 WVP 实例承载 5000+ 设备,集群方案需要 2024+ 的 WVP-PRO 商业版

10.6 个人总结:WVP 5 年的变化

2020 年做视频监控 = 信令网关 + 拉流分发
2024 年做视频监控 = 信令网关 + 流媒体 + AI 分析 + 浏览器低延迟
2026 年做视频监控 = 全套 + 多模态 AI + 边缘计算

WVP-GB28181-pro 这个项目 5 年来依然是国内 Java 视频监控的"事实标准”——只是从"信令网关"演变成了"AI 视频平台入口"。

参考资料(2024+ 补充)

使用 Hugo 构建
主题 StackJimmy 设计