wvp+ZLMediaKit一键部署脚本:国标视频接入从小时级到分钟级 简介这是一套面向安防监控开发与运维人员的GB28181国标接入快速部署包将wvp-GB28181-pro视频平台与ZLMediaKit流媒体服务整合为可直接安装的脚本集合很好地解决了从零编译、手动配置MySQL、Redis、JDK等依赖组件耗时且易出错的问题。资源共含6个文件以4个shell脚本为主体分别覆盖数据库、缓存、Java运行环境及平台核心服务的自动安装另有1个zip资源包存放配套组件1份docx版安装教程则对部署步骤和注意事项进行说明。整个包体约765.58MB下载后按教程修改wvp配置文件中的服务器IP即可对接GB28181摄像头平台各项功能可正常使用。目前已有2534人学习下载适合需要快速搭建视频监控平台进行测试或上线的技术人员也适合希望了解国标设备接入全流程的初学者借助脚本与文档即可降低部署门槛并提升排错效率。 做安防视频接入这一块的人应该都绕不开wvp-GB28181-pro和ZLMediaKit这两个名字。前者是Java生态下的国标GB28181信令平台负责和前端设备做SIP信令交互处理设备注册、目录查询、云台控制、录像回放这些事后者是C写的高性能流媒体服务器负责收流和转流设备推上来的RTP流进来按RTSP、RTMP、HLS、WebRTC这些协议分发给播放端。两个项目配合基本就是目前开源界做国标视频接入的主流方案。不过这套方案有个非常实际的痛点部署起来太折腾。ZLMediaKit需要从源码编译依赖了一堆库wvp-GB28181-pro需要JDK、Maven、MySQL、Redis还有一堆配置文件要改。我去年给一个项目做国标接入光环境搭建就耗了一整天后面换服务器又踩了第二轮坑。所以这次我把整个安装过程整理成了脚本从环境检测到服务启动一条龙跑完目标是把部署时间从小时级压到分钟级。这篇博文就把脚本的设计思路、核心实现、常见问题完整拆开讲不管你是第一次碰国标接入的新手还是想简化部署流程的老手都能直接用上。1. 项目思路为什么要把wvp和ZLMediaKit打包在一起1.1 wvp-GB28181-pro与ZLMediaKit的分工在GB28181的协议体系里设备到平台是两条独立的通道信令通道走SIP媒体通道走RTP。wvp-GB28181-pro负责前者ZLMediaKit负责后者。wvp这边本质是一个基于Spring Boot的Java服务内置了SIP服务器默认监听UDP 5060端口的信令消息。设备上线时向平台发送注册请求wvp校验通过后返回200 OK设备进入在线状态。后续的实时点播、录像回放都是wvp通过SIP INVITE请求携带SDP信息下发到设备告诉设备“往哪个IP的哪个端口推流”。设备收到指令后开始往ZLMediaKit推RTP流。ZLMediaKit那边是一个C写的流媒体服务监听RTSP默认554、RTMP默认1935、HTTP默认80/443等端口同时开启一个配置好的RTP收流端口范围等设备推流上来。它和wvp是两套独立的系统通过HTTP API和WebHook回调对接。wvp发指令让ZLMediaKit“从某个设备的某个通道拉流”ZLMediaKit去拉流后通过回调告诉wvp“流拉到了播放地址是xxxx”。我当时做方案选型的时候其实也对比过直接用wvp自带的媒体能力但发现wvp的定位非常明确——它就是做信令的媒体能力必须委托给ZLM而且wvp官方文档也一直推荐这种组合。所以不用纠结老老实实装两个服务就好。1.2 一键安装脚本的价值如果说wvp和ZLMediaKit是这套方案的两条腿那部署就是让两条腿站起来的门槛。门槛高在哪我列几个实际遇到的问题ZLMediaKit的源码编译依赖cmake、gcc、openssl、ffmpeg等库缺一个编译直接报错wvp的构建要用Maven需要联网下载大量依赖包网络不好直接超时wvp的配置文件application.yml里有数据库、Redis、ZLM地址和密钥等一堆参数要改手动改容易漏数据库需要手工创建并初始化表结构很多人第一次跑起来发现报“table不存在”所以脚本的价值不在于“省几次敲命令的时间”而在于把整个部署过程标准化、可重复。同一套脚本开发环境能装生产环境也能装一个人能装完十个人也能装完。配置一致了后面出问题也好排查不用猜“他当时改了哪里”。2. 脚本整体设计目录结构与环境检测2.1 脚本目录结构与职责划分我打包的安装脚本目录结构是这样的wvp-install/ ├── install.sh # 主安装脚本一键执行 ├── config.ini # 所有可调参数都集中在这里 ├── zlm/ │ └── install_zlm.sh # ZLMediaKit拉取、编译、安装 ├── wvp/ │ └── install_wvp.sh # wvp拉取、编译、配置 ├── sql/ │ └── init_wvp.sql # wvp数据库初始化脚本 └── conf/ └── application.yml # wvp配置文件模板为什么把参数集中放在config.ini里我当时吃过亏。一开始参数是散在脚本里的结果客户要改个端口我得翻半天代码。后来改成所有可调项都放config.ini脚本里只读取不硬编码改动就方便多了。config.ini里主要配置项# 服务端口 SIP_PORT5060 HTTP_PORT8080 MEDIA_PORT10000 # 数据库配置 MYSQL_PASSWORD123456 WVP_DATABASEwvp # ZLMediaKit密钥 MEDIA_SECRET035c73f7-bb6b-4889-a715-d9eb2d192cc8 # 安装目录 INSTALL_DIR/opt/wvp-install2.2 环境检测与依赖安装脚本第一步是检测操作系统。因为整个方案跑在Linux上我主要适配了CentOS 7/8和Ubuntu 18.04/20.04。检测方法是读/etc/os-release根据ID字段判断是CentOS还是Ubuntu然后走不同的安装逻辑if [ -f /etc/os-release ]; then . /etc/os-release OS$ID else echo 无法识别操作系统 exit 1 fi case $OS in centos|rhel) yum install -y gcc gcc-c make cmake git openssl-devel ;; ubuntu|debian) apt update apt install -y build-essential cmake git libssl-dev ;; esac这一步看起来简单但很关键。ZLMediaKit的编译对gcc和cmake版本有要求CentOS 7系统自带的cmake版本才2.8而ZLM需要3.10以上。所以脚本里还要做一个版本检查如果cmake版本太低就用源码编译一个新版cmake装到/usr/local然后PATH里优先用新版。这个坑我踩过不升级cmake直接编译ZLMediaKit报错能让人怀疑人生。JDK这边wvp官方推荐JDK 8我脚本里默认装的是OpenJDK 8。Maven用3.6以上版本配置好阿里云镜像源这样下载依赖会快很多不然Maven中央仓库的下载速度能把人急死。3. 核心安装流程与关键配置3.1 ZLMediaKit的编译与安装流程ZLMediaKit的安装脚本核心流程是拉代码 - 拉子模块 - cmake生成构建文件 - make编译 - 拷贝可执行文件。cd $INSTALL_DIR git clone https://gitee.com/xia-chu/ZLMediaKit.git cd ZLMediaKit git submodule update --init mkdir -p build cd build cmake .. make -j$(nproc)这里有几个容易出错的地方我特别在脚本里做了处理第一一定要执行git submodule update --init。ZLM依赖了一些第三方库比如zltoolkit是以子模块形式引入的。不拉子模块编译的时候直接报找不到头文件。第二make -j后面的参数根据CPU核数动态生成这样多核服务器上编译速度能快不少。我实测在一个4核8G的云服务器上全量编译大概需要10到15分钟如果机器配置低这个时间可能翻倍。第三编译完的可执行文件在release/linux/Debug/MediaServer目录下配置文件是release/linux/Debug/config.ini。启动前需要把config.ini里的相关参数改成实际值[general] mediaServerIdyour_media_server_id [rtsp] port554 [rtmp] port1935 [hook] enable1 # 回调地址 hookUrlhttp://127.0.0.1:8080/index/hookmediaServerId要注意wvp的配置文件里也有一个mediaServerId两个地方必须保持一致否则wvp调用ZLM的API时校验失败报404或401错误。在脚本里我用同一个随机UUID同时写入wvp的application.yml和ZLM的config.ini这样两边永远一致不会出现手动配置时改了这头忘了那头的情况。手动部署的同志建议把这里的值复制到记事本里改哪边都对照着来。3.2 wvp-GB28181-pro的编译与配置wvp的构建相对简单因为它是纯Java项目用Maven打包cd $INSTALL_DIR git clone https://gitee.com/panjialin/wvp-GB28181-pro.git cd wvp-GB28181-pro mvn -DskipTests package -P prod打包完在target目录下生成wvp-pro-*.jar。但这里有个问题wvp的官方代码默认配置是连本地的MySQL和Redis你要是直接跑大概率连不上数据库。所以脚本里要用我准备的application.yml模板替换原来的配置文件把数据库密码、Redis地址、ZLM的IP和密钥都写进去。以下是关键配置项server: port: 8080 sip: ip: 0.0.0.0 port: 5060 media: ip: 127.0.0.1 port: 10000 secret: 035c73f7-bb6b-4889-a715-d9eb2d192cc8 mysql: ip: 127.0.0.1 port: 3306 database: wvp username: root password: 123456 redis: ip: 127.0.0.1 port: 6379这里我遇到过一个大坑wvp和ZLM的通信走的是HTTP的10000端口如果ZLM和wvp不在同一台机器上media.ip就要填ZLM所在机器的IP而且ZLM的HTTP端口默认是10000不是官方文档里某些示例写的8080。我第一次配置时把这个搞混了结果平台界面上设备是注册上了但视频流一直黑屏查了半天才发现是wvp调ZLM API时地址错了。3.3 数据库初始化与Redis处理wvp首次启动前需要先创建数据库并导入初始化SQL。wvp源码的sql目录下有初始化脚本我的安装脚本里也放了一份mysql -uroot -p$MYSQL_PASSWORD -e CREATE DATABASE IF NOT EXISTS wvp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p$MYSQL_PASSWORD wvp $INSTALL_DIR/sql/init_wvp.sql数据库字符集选utf8mb4这个细节值得一说。GB28181平台里会存很多中文通道名、厂商信息如果用默认的latin1或者utf8遇到生僻字或者特殊符号可能存不进去而utf8mb4是MySQL下对UTF-8支持最完整的字符集能覆盖所有Unicode字符。Redis这边wvp用Redis做缓存、存储设备列表等数据启动前必须确认Redis可用。脚本里会先启动Redis服务然后用redis-cli ping检查返回PONG再继续后面的流程。别小看这个检查我遇到过Redis没配密码或者密码不对的情况wvp启动日志里满屏的Connection refused根本定位不到问题。3.4 服务启动与验证所有组件安装配置完成后按依赖顺序启动服务先MySQL再Redis然后ZLMediaKit最后wvp。# 启动MySQL和Redis systemctl start mysqld redis # 启动ZLMediaKit cd $INSTALL_DIR/ZLMediaKit/release/linux/Debug nohup ./MediaServer -c ./config.ini /dev/null 21 # 启动wvp cd $INSTALL_DIR/wvp-GB28181-pro/target nohup java -jar wvp-pro-*.jar /dev/null 21 脚本里我还内置了一个简单的验证流程检查三个关键端口是否在监听netstat -tlnp | grep 8080 netstat -tlnp | grep 5060 netstat -tlnp | grep 10000如果三个端口都在监听基本可以确定服务正常了。然后浏览器访问http://IP:8080默认管理员账号密码是admin/admin登录后就能看到设备管理界面。这里我也做了一个细节处理wvp和ZLM用nohup启动时日志都重定向到固定的日志文件方便后面排查。wvp日志在target目录下的logs里ZLM日志在启动目录下的MediaServer.log——不是./log/目录我当时找日志找了好一会儿。4. 安装部署常见问题与排查技巧实录4.1 设备注册不上怎么办这是国标接入里最常遇到的问题。设备侧填的SIP服务器地址、端口、用户名密码都没错但平台上就是看不到设备上线。排查第一步确认SIP端口是否可达。从设备所在的网络环境用nc测试5060端口nc -uz 192.168.1.100 5060UDP端口测试如果没反应先看防火墙firewall-cmd --list-ports # 或者 iptables -L -n很多情况下部署平台的服务器安全组或iptables只放行了TCP端口UDP 5060没放行设备注册请求根本到不了wvp。还有个容易被忽略的点GB28181设备的国标ID。设备注册时用的国标ID必须和wvp里配置的平台国标ID在同一域内。比如wvp的SIP服务器域是3402000000那设备ID也必须是3402000000开头的20位数字。这个不匹配注册请求会被wvp直接拒绝日志里会有sip server 401之类的提示。4.2 视频流黑屏设备注册上了点播放按钮界面上一片黑。这个问题排查起来要有点耐心。第一步看wvp的日志确认点播时有没有向ZLM发起拉流请求。正常流程是wvp先调ZLM的openRtpServer接口开一个RTP接收端口然后向设备下发INVITE指令。如果日志里没有调ZLM的痕迹大概率是wvp和ZLM的API通信失败了检查media.ip和secret配置。第二步看ZLM的日志确认设备有没有推流上来。ZLM日志里有“收到RTP包”这种打印就说明推流成功。如果设备没有推流可能是设备侧流媒体地址配置错误。很多设备的RTP推流地址要和SIP服务器保持一致但端口是ZLM收流端口范围的某个值通常设备会自动计算但有些老设备需要手动指定。第三步如果ZLM收到了流但还是黑屏可能是编解码或协议转换的问题。检查ZLM配置里是否开启了所需的协议支持比如WebRTC播放需要额外编译支持没编译的话播放页可能就白屏了。4.3 ZLMediaKit编译失败编译失败大部分是依赖问题。最常见的报错是找不到openssl头文件或者cmake版本太低。我脚本里对cmake版本做了升级处理但如果你是自己手动编译建议先用cmake --version确认版本不低于3.10。CentOS 7默认的2.8肯定不行。openssl-devel也要装不然ZLM编译时会报SSL相关错误。还有一个小概率问题拉取ZLM子模块失败。国内网络环境下git submodule update可能超时。脚本里我用了gitee的镜像地址会好很多。如果还有问题可以考虑在git clone时添加--recurse-submodules参数让子模块一起拉取。4.4 wvp启动时报数据库连接失败这个一般是MySQL没起来或者密码不对。检查两件事MySQL服务是否在运行application.yml里的mysql配置和实际是否一致。有个细节我脚本里生成的随机密码会同时写入MySQL和application.yml确保两边一致。手动部署时经常有人改了SQL密码忘了改配置文件结果一脸懵地看报错。5. 实操心得与扩展建议5.1 脚本迭代中的三个教训整套脚本我前后改了三个版本说几个实际体会。第一安装脚本要尽量模拟“从头开始”的场景。我一开始测试脚本是在已经装好环境的机器上跑的自然什么问题都没有。后来找了一台全新机器跑才发现各种依赖缺失、端口冲突问题。现在每改一版脚本我都会在干净的服务器上完整跑一遍确认无误再发布。第二别把脚本写得太死。配置文件模板化、参数集中化是我改到第二版才想明白的。早期脚本里全是硬编码客户要换个MySQL密码就得改脚本。现在config.ini统一管理客户自己改一行就行省了我好多售后时间。第三日志是排查问题的第一手段但也别全指望看服务输出。wvp的日志在logs目录下ZLM的日志在启动目录下如果服务没起来可以先检查日志文件是否存在。如果连日志文件都没有说明进程根本没起来去查Java版本、内存占用这些更基础的问题。5.2 部署后的维护建议最后再分享一个实用维护技巧ZLMediaKit和wvp都支持热切换部署完以后如果发现端口或密钥要改不用重装直接改配置文件、重启服务就行。关键是两个服务之间的联动配置要保持一致我建议在config.ini里统一维护一份别在两边的配置文件里各改各的否则排查问题的时候你会怀疑人生的。另外线上环境建议把wvp和ZLM都注册成systemd服务这样服务异常退出后可以自动拉起服务器重启也能自动恢复。脚本里目前用nohup是为了演示方便生产环境用systemd管理才是正路。这个扩展方向留给接下来要写的第二篇如果这篇反响可以我再把systemd服务模板和监控告警的配置整理出来。本文还有配套的精品资源点击获取