简介:本资源是一套面向GB28181视频接入开发与部署工程师的开箱即用型安装工具包,专为快速搭建WVP-GB28181-Pro流媒体管理平台及配套环境而设计,显著降低ZLMediaKit与国标级视频平台联调的环境配置门槛。压缩包共6个文件(4个Shell脚本、1个ZIP安装包、1个Word教程文档),总大小765.58MB;其中Shell脚本分别用于一键安装WVP主服务、MySQL、Redis和JDK,ZIP包内含必要依赖组件,DOCX文档提供详细配置指引与IP适配说明,确保用户仅需修改WVP配置中的服务器IP即可完成摄像头接入与功能验证。目前已有2553人学习下载,适用于安防集成、智能视觉中台建设等实际项目场景,尤其适合缺乏Linux运维经验但需快速验证GB28181协议对接能力的开发者与实施工程师。
1. 为什么你花三天配不好的 GB28181 流媒体平台,其实只需要一个可复现的安装脚本?
你是不是也经历过:clone 下来 wvp-GB28181-pro 和 ZLMediaKit 两个仓库,翻遍 GitHub Issues、中文论坛、知乎高赞回答,改了application.yml十几处配置,调通 Redis 连接又卡在 SIP 注册超时,最后发现是防火墙没放开 5060/UDP?更糟的是,换台服务器重装——前功尽弃。这不是你技术不行,而是这套组合(wvp-GB28181-pro + ZLMediaKit)本质是个「配置密集型」系统:WVP 是 Java 写的国标信令平台,ZLMediaKit 是 C++ 实现的高性能流媒体中继服务,二者靠 SIP/RTP/RTSP 协议耦合,但文档分散、版本错位、依赖冲突频发。而真正能落地的项目,往往不需要你从零编译 ZLMediaKit、不强求你手写 systemd 服务文件、也不指望你手动处理 WVP 的 MySQL 初始化脚本。这个标题里的“打包好的安装脚本”,指的就是一套经过生产环境验证、覆盖 CentOS 7/8 与 Ubuntu 20.04/22.04、自动拉取指定 commit 版本、预置最小可行配置、并内置健康检查逻辑的 Bash 自动化部署方案。它不是玩具,而是给安防集成商、边缘视频网关开发者、以及需要快速交付 GB28181 接入能力的 IoT 团队用的「第一块砖」——你不需要懂 SIP 状态机,但得知道./install.sh --mode=all --ip=192.168.1.100执行完后,WVP 管理后台在http://192.168.1.100:8080,ZLMediaKit 的 WebRTC 播放页在http://192.168.1.100:8080/webrtc.html。下面,我们就从零开始,把这套脚本的骨架、血肉和神经都拆给你看。
2. 脚本设计逻辑:为什么必须同时控制 WVP 和 ZLMediaKit 的生命周期?
WVP-GB28181-pro 和 ZLMediaKit 不是简单地「装好就能跑」,它们构成一个典型的信令-媒体分离架构:WVP 处理设备注册、目录订阅、SIP 指令下发;ZLMediaKit 负责 RTP 推流接收、转封装、WebRTC/HLS/FLV 分发。二者通过rtsp://127.0.0.1:554/{app}/{stream}或rtp://127.0.0.1:5000这类本地回环地址通信。一旦启动顺序错乱、端口被占、或配置未对齐,整个链路就断在第一步。所以,一个合格的安装脚本,绝不能只做「下载+解压+chmod」。它必须成为这两个服务的「联合指挥官」。我们来看核心设计原则:
2.1 服务依赖关系必须显式声明
ZLMediaKit 必须先于 WVP 启动,且 WVP 启动前需确认 ZLMediaKit 的http_api端口(默认 8080)和media_server端口(默认 1935/554/10000)已监听。脚本里不能用sleep 10这种玄学等待,而要用nc -zv 127.0.0.1 8080+ 重试计数器。实测中,ZLMediaKit 在低配 VPS(1C1G)上冷启动可能耗时 8~12 秒,硬 sleep 5 秒会导致 WVP 初始化失败并反复重启。
# 检查 ZLMediaKit API 是否就绪(脚本内部函数) wait_for_zlmediakit_api() { local max_retries=60 local retry_count=0 while [ $retry_count -lt $max_retries ]; do if nc -zv 127.0.0.1 8080 >/dev/null 2>&1; then echo "[INFO] ZLMediaKit HTTP API is ready." return 0 fi sleep 1 ((retry_count++)) done echo "[ERROR] Timeout waiting for ZLMediaKit API (8080)." return 1 }提示:这里用
nc(netcat)而非curl,是因为 ZLMediaKit 启动初期可能返回 503,但端口已监听——nc只判断端口通不通,更可靠;curl -f http://127.0.0.1:8080/index/api/getServerConfig则要求服务完全就绪,容易误判。
2.2 配置生成必须双向绑定
WVP 的application.yml里要填 ZLMediaKit 的推流地址、拉流地址、HTTP API 地址;ZLMediaKit 的config.ini里又要指定 WVP 的 SIP Server IP、端口、以及是否启用国标级联。脚本必须用模板引擎(如sed或envsubst)动态注入,而不是让用户手动改。例如,WVP 的sip.ip字段必须和宿主机实际 IP 一致(不能写127.0.0.1),否则下级设备注册会失败;而 ZLMediaKit 的rtp_proxy若开启,其proxy_ip必须设为宿主机外网 IP,否则公网设备无法穿透。
# 生成 WVP application.yml(关键片段) cat > "$WVP_HOME/conf/application.yml" <<EOF server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/wvp?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: ${MYSQL_ROOT_PASSWORD:-123456} gb28181: sip: ip: ${HOST_IP} # ← 宿主机真实 IP,非 127.0.0.1 port: 5060 transport: UDP domain: ${SIP_DOMAIN:-34020000002000000001} password: ${SIP_PASSWORD:-123456} media: server-ip: ${HOST_IP} # ← WVP 告诉设备:媒体流推到这儿 server-port: 10000 rtp-proxy: true zlm: http-api-url: http://${HOST_IP}:8080/index/api/ stream-push-url: rtsp://${HOST_IP}:554/ stream-pull-url: rtsp://${HOST_IP}:554/ EOF注意:
server-ip和zlm.stream-push-url中的${HOST_IP}必须是脚本运行时通过hostname -I | awk '{print $1}'或ip route | grep src | awk '{print $9}'获取的真实出口 IP。很多翻车案例,根源就是脚本用了127.0.0.1或localhost,导致设备注册成功但流无法建立。
2.3 二进制分发策略决定部署成败
ZLMediaKit 官方只提供 Linux x86_64 静态编译版(无 glibc 依赖),但 wvp-GB28181-pro 的 release 包里wvp.jar是 Spring Boot fat jar,需 JDK 11+。脚本必须解决三个问题:
- JDK 版本锁定:Ubuntu 22.04 默认带 JDK 18,但 WVP 3.5.x 经测试在 JDK 17 上最稳,故脚本内嵌
jdk-17.0.1_linux-x64_bin.tar.gz并设JAVA_HOME; - ZLMediaKit 版本对齐:WVP 3.5.0 要求 ZLMediaKit ≥ v4.5,但 v4.7 有 RTCP 丢包率统计 bug,故脚本固定拉取
v4.6.1release; - 权限隔离:ZLMediaKit 必须以非 root 用户运行(安全基线要求),而 WVP 的 MySQL 初始化需 root 权限。脚本用
useradd -r -s /bin/false zlmediakit创建专用用户,并用sudo -u zlmediakit启动。
3. 安装脚本实操:从空服务器到可访问后台的 7 个原子步骤
我们以 Ubuntu 22.04 为例,完整走一遍脚本执行流程。脚本名为install_wvp_zlm.sh,支持--mode=all(全量)、--mode=zlm-only(仅 ZLMediaKit)、--mode=wvp-only(仅 WVP)三种模式。以下为--mode=all的核心路径,每步均附命令、预期输出及原理说明。
3.1 步骤一:预检系统环境与基础依赖
脚本首先进入precheck()函数,检测:OS 发行版及版本、可用内存(≥2G)、磁盘空间(≥10G)、是否已安装curl wget unzip jq、systemd是否可用。特别注意:CentOS 7 必须启用 EPEL 源,否则jq无法安装;Ubuntu 22.04 的systemd-resolved有时会干扰 SIP DNS 解析,脚本会自动停用并切换至8.8.8.8。
# 脚本内 precheck 函数节选 precheck() { echo "[STEP 1/7] Pre-checking system environment..." # 检测 OS if [[ -f /etc/os-release ]]; then . /etc/os-release OS_NAME=$ID OS_VERSION=$VERSION_ID else echo "[ERROR] Unsupported OS. Only Ubuntu/CentOS supported." exit 1 fi # 检测内存 local mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}') if [ "$mem_kb" -lt 2097152 ]; then # < 2G echo "[WARN] Memory less than 2GB. May cause OOM during ZLMediaKit startup." fi # 检测 systemd if ! command -v systemctl &> /dev/null; then echo "[ERROR] systemd not found. This script requires systemd." exit 1 fi }原理说明:很多用户在 OpenVZ 或 Docker 容器里跑失败,就是因为容器默认无
systemd。此步直接拦截,避免后续所有操作白费。
3.2 步骤二:创建独立工作目录与用户
脚本在/opt下创建wvp-zlm目录,并创建wvp和zlmediakit两个系统用户,分别归属各自服务。关键点:zlmediakit用户禁用 shell(/bin/false),主目录设为/var/lib/zlmediakit,并赋予对/opt/wvp-zlm/zlmediakit的读写权。这是为后续systemd服务文件中User=zlmediakit做准备。
# 创建目录与用户(脚本内) mkdir -p /opt/wvp-zlm groupadd -g 1001 wvp groupadd -g 1002 zlmediakit useradd -r -u 1001 -g wvp -d /var/lib/wvp -s /bin/false wvp useradd -r -u 1002 -g zlmediakit -d /var/lib/zlmediakit -s /bin/false zlmediakit chown -R wvp:wvp /opt/wvp-zlm/wvp chown -R zlmediakit:zlmediakit /opt/wvp-zlm/zlmediakit参数说明:
-r表示创建系统用户(UID < 1000),符合安全规范;-d指定家目录,避免服务进程在/root下写临时文件;chown确保服务以正确用户身份运行,防止权限拒绝(Permission denied)错误。
3.3 步骤三:下载并解压 ZLMediaKit 静态二进制包
脚本从 ZLMediaKit GitHub Release 页面(https://github.com/ZLMediaKit/ZLMediaKit/releases)下载ZLMediaKit_linux.tar.gz,校验 SHA256(官方提供 checksum 文件),解压到/opt/wvp-zlm/zlmediakit。重点:不编译,不依赖 GCC,不碰 cmake。因为编译耗时长、易出错,且静态版已满足 99% 场景需求。
# 下载 ZLMediaKit(脚本内) ZLM_VERSION="v4.6.1" ZLM_URL="https://github.com/ZLMediaKit/ZLMediaKit/releases/download/${ZLM_VERSION}/ZLMediaKit_linux.tar.gz" ZLM_SHA256="a1b2c3d4e5f6...7890" # 实际值从官网 checksums.txt 获取 cd /tmp curl -fsSL "$ZLM_URL" -o ZLMediaKit_linux.tar.gz echo "${ZLM_SHA256} ZLMediaKit_linux.tar.gz" | sha256sum -c - tar -xzf ZLMediaKit_linux.tar.gz -C /opt/wvp-zlm/ mv /opt/wvp-zlm/ZLMediaKit_linux /opt/wvp-zlm/zlmediakit为什么选 v4.6.1?实测发现:v4.5.0 对 H.265 设备兼容性差;v4.7.0 的
rtp_proxy模式在高并发下 RTP 包序号错乱;v4.6.1 是目前最平衡的稳定版,且 WVP 3.5.0 的zlm模块文档明确标注兼容此版本。
3.4 步骤四:生成 ZLMediaKit 配置文件 config.ini
ZLMediaKit 的config.ini是其心脏。脚本用模板填充关键 section:[general](日志路径、工作线程数)、[http](API 端口、跨域)、[rtp](RTP 端口范围、是否启用代理)、[gb28181](国标设备接入参数)。其中rtp.port_range必须设为10000-10100(而非默认10000-65535),否则 WVP 的rtp-proxy无法精准映射;gb28181.enable必须为1,否则设备无法注册。
# 生成的 /opt/wvp-zlm/zlmediakit/config.ini 关键片段 [general] log_level=3 log_path=/var/log/zlmediakit/ thread_num=4 [http] port=8080 cross_origin=* [rtp] port_range=10000-10100 enable_rtp_proxy=1 rtp_proxy_timeout=30 [gb28181] enable=1 sip_port=5060 sip_listen_ip=0.0.0.0 media_server_ip=${HOST_IP} # ← 设备拉流时用的 IP注意:
media_server_ip必须和 WVP 的gb28181.media.server-ip一致,且必须是宿主机可路由的 IP。若服务器在 NAT 后,此处应填公网 IP,ZLMediaKit 会自动处理 STUN。
3.5 步骤五:下载并初始化 WVP-GB28181-pro
脚本从 WVP GitHub Release(https://github.com/648540858/wvp-GB28181-pro/releases)下载wvp-3.5.0-release.tar.gz,解压到/opt/wvp-zlm/wvp。接着,自动初始化 MySQL 数据库:创建wvp库、导入sql/wvp.sql(含设备表、用户表、级联表),并设置 root 密码(若未指定则用默认123456)。这一步省去用户手动登录 MySQL 的麻烦。
# 初始化 MySQL(脚本内) mysql -u root -p"${MYSQL_ROOT_PASSWORD:-123456}" -e "CREATE DATABASE IF NOT EXISTS wvp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" mysql -u root -p"${MYSQL_ROOT_PASSWORD:-123456}" wvp < /opt/wvp-zlm/wvp/sql/wvp.sql血泪经验:WVP 的 SQL 脚本里
CREATE TABLE语句末尾没有ENGINE=InnoDB,在 MySQL 8.0+ 上可能因默认引擎变更而失败。脚本已预处理该 SQL 文件,全局追加ENGINE=InnoDB。
3.6 步骤六:生成 systemd 服务文件并启用
脚本为 ZLMediaKit 和 WVP 分别生成/etc/systemd/system/zlmediakit.service和/etc/systemd/system/wvp.service。关键参数:Type=simple(非 forking)、Restart=on-failure(崩溃自动重启)、RestartSec=5(重启间隔)、LimitNOFILE=65535(突破文件描述符限制)。WVP 服务还必须After=zlmediakit.service,确保启动顺序。
# /etc/systemd/system/zlmediakit.service [Unit] Description=ZLMediaKit Media Server After=network.target [Service] Type=simple User=zlmediakit Group=zlmediakit WorkingDirectory=/opt/wvp-zlm/zlmediakit ExecStart=/opt/wvp-zlm/zlmediakit/ZLMediaKit -c /opt/wvp-zlm/zlmediakit/config.ini Restart=on-failure RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target为什么不用
Type=forking?ZLMediaKit 启动后不会 fork 子进程,主进程一直存活。用forking会导致 systemd 误判服务状态为inactive。
3.7 步骤七:启动服务并验证端口监听
脚本执行systemctl daemon-reload,然后systemctl enable --now zlmediakit wvp。最后,用ss -tuln检查端口:5060/udp(SIP)、8080/tcp(ZLM API)、1935/tcp(RTMP)、554/tcp(RTSP)、8080/tcp(WVP 后台)是否全部 LISTEN。任一缺失,脚本立即报错并输出journalctl -u zlmediakit -n 50日志。
# 验证端口(脚本内) expected_ports=("5060/udp" "8080/tcp" "1935/tcp" "554/tcp") for port in "${expected_ports[@]}"; do if ! ss -tuln | grep -q ":${port%%/*}.*${port##*/}"; then echo "[ERROR] Port $port not listening. Check service logs." journalctl -u zlmediakit -n 50 exit 1 fi done echo "[SUCCESS] All services started. WVP: http://${HOST_IP}:8080, ZLM: http://${HOST_IP}:8080/webrtc.html"提示:
ss -tuln比netstat更快更准,且无需安装额外包;journalctl -u zlmediakit -n 50直接定位最近 50 行日志,比翻tail -f /var/log/zlmediakit/log.log高效得多。
4. 避坑指南:生产环境踩过的 5 个真实坑,每个都让你重装半小时
这些不是理论假设,而是我在三个不同客户现场(智慧工地、雪亮工程、校园安防)亲手填过的坑。每一条都对应一个具体的journalctl错误日志和解决方案。
4.1 现象:WVP 启动后日志循环打印Failed to connect to ZLMediaKit API: Connection refused
原因:ZLMediaKit 的config.ini中[http] port=8080被注释或写成8081,而 WVP 的application.yml里zlm.http-api-url仍指向:8080,导致连接被拒。
解决:检查/opt/wvp-zlm/zlmediakit/config.ini第 32 行port=值是否为8080,且未被#注释;再核对/opt/wvp-zlm/wvp/conf/application.yml中zlm.http-api-url的端口是否匹配。脚本已加入校验逻辑,但手动修改后需重新运行./install.sh --mode=wvp-only。
4.2 现象:设备能注册成功,但点击“实时视频”黑屏,WVP 日志报Stream not found: 34020000001320000001_0000000001
原因:ZLMediaKit 的rtp.port_range设置过窄(如10000-10001),而设备实际使用10005端口推流,ZLMediaKit 拒收该端口 RTP 包。
解决:将config.ini中rtp.port_range改为10000-10100,执行systemctl restart zlmediakit。实测 100 个设备并发时,10000-10050就够用,但留 50 个余量更稳妥。
4.3 现象:Ubuntu 22.04 上systemctl start zlmediakit报错Failed to start zlmediakit.service: Unit zlmediakit.service not found
原因:脚本执行中途被 Ctrl+C 中断,/etc/systemd/system/zlmediakit.service文件未写入完成,或systemctl daemon-reload未执行。
解决:手动检查/etc/systemd/system/zlmediakit.service是否存在且内容完整;若缺失,运行./install.sh --mode=zlm-only重装 ZLMediaKit 部分;若存在但无效,执行systemctl daemon-reload && systemctl start zlmediakit。
4.4 现象:WVP 后台登录后,设备列表为空,MySQL 日志显示Access denied for user 'root'@'localhost'
原因:脚本执行时未传入MYSQL_ROOT_PASSWORD,使用了默认密码123456,但服务器 MySQL root 密码已被修改,导致 WVP 无法连接数据库。
解决:编辑/opt/wvp-zlm/wvp/conf/application.yml,修改spring.datasource.password为当前 MySQL root 密码;然后systemctl restart wvp。脚本已支持--mysql-password=xxx参数,首次安装务必显式指定。
4.5 现象:ZLMediaKit 启动后 CPU 占用 100%,top显示ZLMediaKit进程持续满载
原因:config.ini中[rtp] enable_rtp_proxy=0(关闭代理),而 WVP 的gb28181.media.rtp-proxy=true,导致 WVP 尝试通过 ZLMediaKit 的 RTP 代理转发流,但 ZLMediaKit 未启用该功能,陷入忙等循环。
解决:统一开关——要么config.ini设enable_rtp_proxy=1且 WVP 设rtp-proxy=true,要么两者都设为false。推荐前者,因rtp-proxy=true能解决大部分 NAT 穿透问题。
5. 进阶技巧:如何用这套脚本快速验证设备兼容性与流稳定性?
安装只是起点。真正考验脚本价值的,是你能否在 10 分钟内,用一台笔记本模拟海康、大华、宇视三款主流设备,验证它们能否注册、能否拉流、能否承受 30 分钟压力。以下是我在交付现场打磨出的三板斧:
5.1 用 SIPP 模拟百台设备并发注册(不需真实硬件)
SIPP 是 SIP 协议压测神器。脚本配套提供sipp_register.xml场景文件,可模拟 100 台设备向 WVP 注册。只需在安装完的服务器上执行:
# 安装 sipp(脚本已预置一键安装函数) apt-get install -y sipp # 启动压测:100 台设备,每秒 5 台注册,超时 30 秒 sipp -sf sipp_register.xml -inf device_list.csv \ -p 5061 -m 100 -l 5 -timeout 30s \ ${HOST_IP}:5060device_list.csv格式为:
34020000001320000001,12345678,34020000002000000001 34020000001320000002,12345678,34020000002000000001 ...原理:SIPP 读取 CSV,为每行生成唯一
DeviceID和Password,向 WVP 的5060/UDP发送 REGISTER 请求。脚本内置的sipp_register.xml已适配 GB28181 的 SIP 头字段(如Contact: <sip:34020000001320000001@192.168.1.100:5060>),无需修改。
5.2 用 FFmpeg 推流验证 ZLMediaKit 媒体链路
不用摄像头,用 FFmpeg 生成测试流直推 ZLMediaKit。脚本提供push_test_stream.sh:
#!/bin/bash # 推送 640x480 H.264 测试流,流名 test_001 ffmpeg -re -f lavfi -i testsrc=size=640x480:rate=25 -vcodec libx264 \ -preset ultrafast -tune zerolatency -b:v 500k -maxrate 500k \ -bufsize 1000k -pix_fmt yuv420p -g 50 \ -f rtsp "rtsp://${HOST_IP}:554/test_001"执行后,打开http://${HOST_IP}:8080/webrtc.html?app=test&stream=test_001,即可看到 WebRTC 播放画面。若黑屏,立刻查 ZLMediaKit 日志:grep "test_001" /var/log/zlmediakit/log.log,通常能定位到编码格式不支持或 GOP 设置异常。
5.3 用 Prometheus + Grafana 监控关键指标(脚本已集成)
脚本在安装 ZLMediaKit 时,自动启用其内置 Prometheus Exporter(config.ini中[prometheus] enable=1)。然后部署轻量 Prometheus(prometheus-2.45.0.linux-amd64.tar.gz)和预配置 Grafana Dashboard。关键监控项表格如下:
| 指标名 | Prometheus 查询语句 | 告警阈值 | 说明 |
|---|---|---|---|
| ZLMediaKit 在线设备数 | count(zlmediakit_gb28181_device_online{job="zlmediakit"}) | < 1 | 设备离线,检查 SIP 注册 |
| RTP 接收丢包率 | rate(zlmediakit_rtp_recv_loss{job="zlmediakit"}[5m]) | > 0.05 | 网络拥塞,需查交换机 QoS |
| WVP HTTP 5xx 错误率 | rate(http_server_requests_seconds_count{status=~"5.."}[5m]) / rate(http_server_requests_seconds_count[5m]) | > 0.01 | WVP 后端异常,查数据库连接 |
| ZLMediaKit 内存使用率 | process_resident_memory_bytes{job="zlmediakit"} / 1024 / 1024 | > 1500 | 内存泄漏,需升级 ZLMediaKit |
这套监控不依赖外部云服务,全部跑在本机,
prometheus.yml已预设抓取http://127.0.0.1:9090/metrics(ZLMediaKit)和http://127.0.0.1:8080/actuator/prometheus(WVP),开箱即用。
我坚持把脚本做成「一次安装,三年可用」,不是因为它多完美,而是因为每次重装,你损失的不只是两小时,而是客户对你专业性的信任。现在,你手里有了这个脚本,也知道了它怎么工作、哪里会卡、怎么验证——接下来,就是把它部署到你的第一台边缘服务器上,打开浏览器,输入那个 IP,看着设备列表从空变满,看着视频流从黑变亮。那种确定感,比任何教程都实在。希望帮到你。
本文还有配套的精品资源,点击获取