
简介本资源是基于GB28181国标开发的wvp-GB28181服务端平台完整源码工程面向视频监控系统开发者、安防集成工程师及物联网协议学习者解决GB28181标准在实际项目中的注册、心跳、Invite媒体协商等核心流程落地难题适用于平安城市、智慧交通等需跨平台视频互联的实战场景。压缩包含169个文件以58个Java业务逻辑文件实现SIP信令处理、设备管理、流媒体控制等、78个XML配置与协议模板文件含国标消息体定义、设备目录结构、SIP头字段映射为主干辅以YML配置、日志与权限管理相关脚本整体仅579KB轻量易部署。已有2710人学习下载提供可直接编译运行的完整工程结构、标准化的模块划分如sip、device、stream、auth、关键流程注释详尽的源码及配套说明文档助读者快速掌握GB28181服务端开发范式与协议调试要点。1. WVP-GB28181 不是“又一个国标平台”它是能当天部署、次日接入海康/大华/宇视设备的轻量级流媒体中枢你手头有一台刚出厂的海康IPC设备已按GB/T 28181-2016配置好SIP注册参数但用Wireshark抓包发现REGISTER一直超时或者你正被甲方催着“三天内把37路老款大华NVR拉进统一视频平台”而现成的商用平台动辄要配K8s集群Redis哨兵专用GPU转码卡——这时候WVP-GB28181 就不是“开源项目”那么简单了。它是一套不依赖Java容器、不强制MySQL、单机4核8G即可承载200路国标信令50路H.265实时流转发的精简型GB28181服务端核心逻辑全由Spring Boot Netty实现信令层与媒体流层解耦清晰连wvp-gb28181这个仓库名都透着一股“只干GB28181这一件事”的狠劲。它不提供Web管理界面得配配套的wvp-web也不打包FFmpeg得自己装但正因如此它成了安防集成商、边缘AI盒子厂商、甚至高校实验室做国标协议教学时最常被“抄底复用”的那个底层服务模块。如果你需要的是可嵌入、可裁剪、可调试、能看清每条SIP消息字段含义的GB28181服务而不是一个黑匣子式的“开箱即用平台”那WVP就是你该从源码编译的第一站。2. 从零构建 WVP-GB28181编译、配置、启动三步闭环WVP 的官方发布包如wvp-4.3.0.jar虽带application.yml模板但实际部署中90%的翻车都源于配置项与真实网络拓扑错位。我建议跳过jar包直跑坚持源码编译——不是为了炫技而是因为pom.xml里藏着三个关键开关netty-sctp是否启用影响华为/部分定制IPC兼容性、spring-boot-starter-webflux是否排除避免与旧版Netty冲突、以及ffmpeg路径是否硬编码为/usr/bin/ffmpeg这在Docker里必炸。下面以Ubuntu 22.04 OpenJDK 17 FFmpeg 6.1为基准环境走一遍真正能落地的构建链。2.1 源码拉取与基础依赖校验先确认Java和Maven版本必须严格匹配WVP主干分支v4.x要求JDK 17且Maven 3.8.6以上。低版本会导致spring-boot-maven-plugin:3.1.0插件解析失败报错Plugin execution not covered by lifecycle configuration——这不是IDE问题是Maven本身对Spring Boot 3.x生命周期绑定不兼容。# 验证Java版本必须输出17.x java -version # 输出应类似openjdk version 17.0.8 2023-07-18 # 验证Maven必须3.8.6 mvn -v # 输出应含Apache Maven 3.8.7 # 拉取官方源码注意不要用GitHub页面上的zip下载会缺.gitmodules git clone https://gitee.com/610546279/wvp-GB28181.git cd wvp-GB28181 git checkout v4.3.0 # 稳定分支v4.4.0尚有SIP ACK重传bug提示WVP使用Git Submodule管理wvp-common和wvp-protocol两个核心模块。若git clone后ls -la看不到common/和protocol/目录请立即执行git submodule update --init --recursive否则编译时会报package com.genersoft.wvp.common.exception does not exist。22.2 编译前的关键配置预埋WVP的pom.xml默认开启netty-sctp支持但Ubuntu默认不装SCTP内核模块强行启用会导致启动时报java.lang.UnsatisfiedLinkError: no netty_transport_native_sctp in java.library.path。解决方案不是装sctp而是在编译前关闭它!-- 修改 wvp-GB28181/pom.xml找到 profiles 标签下 iddefault 的 profile -- profile iddefault/id activation activeByDefaulttrue/activeByDefault /activation properties !-- 在此处新增一行禁用SCTP -- netty.sctp.enabledfalse/netty.sctp.enabled /properties /profile同时检查wvp-GB28181/wvp-server/src/main/resources/application.yml中的ffmpeg路径。默认值/usr/bin/ffmpeg在Docker容器里大概率不存在但不要直接改成ffmpeg会因PATH未生效而找不到而应改为绝对路径并确保容器内已挂载# application.yml 片段 media: ffmpeg-path: /opt/ffmpeg/bin/ffmpeg # 后续Dockerfile中需对应挂载 ffprobe-path: /opt/ffmpeg/bin/ffprobe2.3 执行编译并验证jar结构执行编译命令时务必加-Dmaven.test.skiptrue跳过单元测试——WVP的测试用例依赖本地Redis和MySQL而我们目标是快速产出可运行jarmvn clean package -Dmaven.test.skiptrue -P default # 成功后生成物在 wvp-GB28181/wvp-server/target/wvp-server-4.3.0.jar验证jar是否包含全部依赖这是WVP能“单jar运行”的前提jar -tf wvp-server/target/wvp-server-4.3.0.jar | grep -E (netty|spring|ffmpeg) | head -10你应该看到类似输出BOOT-INF/lib/netty-transport-4.1.94.Final.jar BOOT-INF/lib/spring-boot-starter-web-3.1.0.jar BOOT-INF/lib/ffmpeg-cli-wrapper-1.12.jar若无ffmpeg-cli-wrapper说明wvp-common子模块未正确拉取或编译失败需回退检查Submodule步骤。2.4 启动前的最小化配置清单WVP启动不依赖数据库但必须配置三项网络参数才能完成SIP注册。以下是最小application.yml改写模板仅保留必需字段server: port: 1080 address: 0.0.0.0 sip: ip: 192.168.1.100 # 本机对外IP非127.0.0.1必须与IPC配置的“平台IP”一致 port: 5060 transport: UDP expires: 3600 media: ip: 192.168.1.100 # 与sip.ip必须相同GB28181媒体流RTP地址由此生成 port-range: 30000-30100 ffmpeg-path: /usr/bin/ffmpeg redis: host: 127.0.0.1 port: 6379 database: 0注意sip.ip和media.ip填错是新手第一大坑。很多教程写成localhost或127.0.0.1结果IPC能发REGISTER但收不到200 OK——因为WVP回复的Contact头里带127.0.0.1:5060IPC根本无法反向连接。务必填服务器真实局域网IP。3. 设备接入实战海康IPC注册、音视频拉流、语音对讲三连通WVP本身不提供设备管理UI所有操作靠HTTP API或直接改数据库。但别慌——它的API设计极度克制只有6个核心接口就覆盖全部设备生命周期。我们以海康DS-2CD3T86G2-LIU固件V5.6.10为例走通从注册到对讲的全链路。3.1 设备注册用curl触发SIP REGISTER海康IPC的GB28181配置入口在配置 网络 高级设置 平台对接 GB28181。关键参数如下平台ID31011500991320000001示例需与WVP配置的platform.id一致平台IP192.168.1.100即WVP的sip.ip平台端口5060本地端口5060IPC自身SIP监听端口心跳间隔60秒配置保存后IPC会自动发送REGISTER。此时在WVP服务器执行# 查看WVP日志过滤SIP信令 tail -f logs/wvp.log | grep -i register\|200 ok正常应看到INFO c.g.w.s.s.SipMessageHandler - Received REGISTER from /192.168.1.200:5060 INFO c.g.w.s.s.SipMessageHandler - Send 200 OK to /192.168.1.200:5060若只看到REGISTER无200 OK90%是防火墙拦截UDP 5060端口。用sudo ufw status检查开放命令为sudo ufw allow 5060/udp sudo ufw allow 30000:30100/udp # RTP媒体端口范围3.2 视频拉流通过WVP内置WebRTC网关WVP不自带播放器但提供标准WebRTC接口。假设设备编码为310115009913200000013101150000000001平台ID设备ID拉流URL为http://192.168.1.100:1080/webrtc/player.html?applivestream310115009913200000013101150000000001原理说明player.html是WVP内置的简易WebRTC播放页它调用/api/webrtc/start接口发起拉流。WVP收到请求后先向IPC发送SUBSCRIBE订阅视频流IPC回送NOTIFY携带SDPWVP再将SDP转给浏览器。整个过程无需额外信令服务器如Janus因为WVP自己实现了WebRTC信令中继。3.3 语音对讲GB28181 Annex D流程实操GB28181语音对讲Annex D比视频复杂需双向建立RTP通道。WVP通过/api/device/talk接口触发# 发起对讲POST curl -X POST http://192.168.1.100:1080/api/device/talk \ -H Content-Type: application/json \ -d { deviceId: 310115009913200000013101150000000001, streamType: 35, # 音频流类型固定值 mediaServerId: default }成功返回{code:0,msg:success,data:{callId:1234567890abcdef}}此时WVP会向IPC发送INFO消息IPC回送200 OK后WVP开始监听本地UDP端口如30001接收音频流。关键点在于浏览器端需用Web Audio API采集麦克风并将PCM数据编码为G.711 A-law再通过RTCPeerConnection发送到WVP分配的RTP端口——这部分逻辑由配套的wvp-web前端实现若自行开发必须严格遵循GB28181 Annex D的RTP payload type 8PCMA封装规范。4. 避坑指南五个让集成工程师凌晨三点还在抓包的真实问题WVP文档简洁得近乎吝啬但生产环境里的坑往往藏在参数组合的缝隙里。以下是我在37个现场项目中踩出的血泪经验按现象→原因→解决三段式整理拒绝模糊描述。4.1 现象IPC注册成功但WVP日志持续刷Device not found: xxx无法拉流原因WVP默认只接受platform.id与配置文件中sip.platform-id完全一致的设备。海康IPC的平台ID配置项名为“国标编号”但部分固件如V5.4.10会自动在末尾补零导致实际发送的REGISTER中To: sip:310115009913200000010000...比配置多4个0。解决在application.yml中启用ID截断模式sip: platform-id: 31011500991320000001 platform-id-length: 20 # 强制截取前20位匹配4.2 现象视频能拉但画面卡顿严重Wireshark显示大量RTP丢包原因WVP的media.port-range如30000-30100与Linux系统可用端口范围冲突。Ubuntu默认net.ipv4.ip_local_port_range 32768 60999当WVP随机选到32768以下端口时内核拒绝绑定。解决扩大系统端口范围并重启WVPecho net.ipv4.ip_local_port_range 10000 65535 | sudo tee -a /etc/sysctl.conf sudo sysctl -p4.3 现象语音对讲发起后IPC端无声音WVP日志报Failed to start talk: media server not found原因WVP的语音对讲依赖独立的media-server模块默认使用ffmpeg进行音频转码。若ffmpeg-path指向的二进制不支持libopus如Ubuntu apt安装的ffmpeg则无法生成WebRTC兼容的Opus流。解决编译带Opus支持的FFmpeg关键参数./configure --enable-libopus --enable-gpl --enable-nonfree make -j$(nproc) sudo make install然后在application.yml中指定新路径ffmpeg-path: /usr/local/bin/ffmpeg4.4 现象多台IPC注册后WVP内存持续增长至OOMjstat -gc显示Old Gen满原因WVP的DeviceManager缓存设备对象默认永不过期且未实现LRU淘汰。200台设备长期运行后每个设备维持约1.2MB内存含SIP对话状态、媒体流元数据。解决在application.yml中添加设备缓存策略device: cache: max-size: 100 # 最多缓存100台设备 expire-after-write: 30m # 写入30分钟后过期4.5 现象Docker部署后IPC能注册但RTP流始终无法到达WVP容器原因Docker默认使用bridge网络宿主机iptables会SNAT UDP包导致IPC发往192.168.1.100:30000的RTP包被改源IPWVP收包时校验失败。解决启动容器时添加--network host参数让WVP直接使用宿主机网络栈docker run -d \ --network host \ -v /path/to/application.yml:/app/application.yml \ -v /path/to/ffmpeg:/opt/ffmpeg \ wvp-server:4.3.05. 进阶技巧用Python脚本自动化设备批量注册与状态巡检WVP的HTTP API虽简单但手动调用50台设备的注册请求显然不现实。我写了一个轻量级Python巡检脚本wvp_batch.py它能① 读取Excel设备列表自动生成注册请求② 每5分钟轮询设备在线状态③ 发现离线设备自动触发告警邮件。核心逻辑不在框架而在如何绕过WVP的API限流和会话校验。5.1 设备列表Excel格式定义WVP不校验设备密码但要求serialNumber字段唯一。Exceldevices.xlsx必须含三列deviceIdnamemanufacturer310115009913200000013101150000000001前门岗HIKVISION310115009913200000013101150000000002后门岗DAHUA注意deviceId必须是20位平台ID20位设备ID拼接共40位这是GB28181强制要求。海康IPC的设备ID可在Web界面“系统配置 系统 系统信息”中查看。5.2 批量注册脚本核心逻辑# wvp_batch.py import requests import pandas as pd from time import sleep WVP_URL http://192.168.1.100:1080 HEADERS {Content-Type: application/json} def register_device(device): 向WVP注册单台设备 payload { deviceId: device[deviceId], name: device[name], manufacturer: device[manufacturer], model: unknown, firmware: unknown, registerWay: 0, # 0主动注册1被动注册 status: 1 # 1在线 } try: resp requests.post(f{WVP_URL}/api/device, jsonpayload, timeout5) if resp.status_code 200: print(f✓ {device[name]} 注册成功) else: print(f✗ {device[name]} 注册失败: {resp.text}) except Exception as e: print(f✗ {device[name]} 请求异常: {e}) # 主流程 df pd.read_excel(devices.xlsx) for _, row in df.iterrows(): register_device(row.to_dict()) sleep(0.3) # 避免WVP API限流默认10qps5.3 状态巡检与告警机制WVP的/api/device/status接口返回JSON数组但不包含设备最后心跳时间。我们只能通过/api/device/{deviceId}获取单台详情其中keepaliveTime字段即最后心跳时间戳毫秒。巡检逻辑如下字段说明判定逻辑keepaliveTime最后心跳时间戳若当前时间 - keepaliveTime 1200002分钟判定离线status设备状态码0离线1在线2报警中def check_device_status(device_id): 检查单台设备在线状态 try: resp requests.get(f{WVP_URL}/api/device/{device_id}, timeout3) if resp.status_code ! 200: return False, API异常 data resp.json().get(data, {}) last_heartbeat data.get(keepaliveTime, 0) now_ms int(time.time() * 1000) if now_ms - last_heartbeat 120000: return False, f心跳超时: {last_heartbeat} return True, 在线 except Exception as e: return False, f请求失败: {e} # 巡检循环 while True: offline_devices [] for device_id in device_list: is_online, reason check_device_status(device_id) if not is_online: offline_devices.append((device_id, reason)) if offline_devices: send_alert_email(offline_devices) # 自行实现邮件函数 time.sleep(300) # 每5分钟巡检一次5.4 关键参数表WVP API高频调用参数速查接口方法必填参数说明调试技巧/api/devicePOSTdeviceId,name设备注册registerWay0时WVP主动向IPC发SUBSCRIBE/api/device/{id}GET无获取设备详情keepaliveTime单位为毫秒需除1000转秒/api/device/{id}/streamPOSTstreamType1主码流开启视频流streamType2为子码流35为音频流/api/device/talkPOSTdeviceId,streamType35启动语音对讲必须先调用/stream开启音频流/api/media_serverGET无获取媒体服务器列表WVP默认只有一台default无需额外配置从那以后我每次部署WVP都强制走一遍tcpdump -i any port 5060 -w sip.pcap抓包对照RFC3261逐行比对ACK/200 OK的Via、Contact、Record-Route字段是否符合预期——不是因为信不过WVP而是因为IPC厂商对GB28181的实现各有各的“理解”。希望帮到你。本文还有配套的精品资源点击获取