51 KiB
GoWVP (Owl) + ZLMediaKit 飞腾S5000 + 统信UOS20 联网部署手册
文档版本: v1.0 生成日期: 2026-04-29 适用环境: 飞腾S5000C (ARM64) + 统信UOS20服务器版(1070) + 联网环境 目标系统: ARM64 (aarch64) / ARMv8.2
更新记录
| 版本号 | 更新人 | 更新日期/时间 | 更新内容 |
|---|---|---|---|
| v1.0 | 浮浮酱 | 2026-04-29 | 初始版本,基于离线部署手册 v1.2 适配联网环境 |
目录
一级导航
二级导航
一、文档概述
二、环境说明
三、环境初始化
四、服务部署
五、配置联动
六、验证步骤
七、常见问题排查
- 7.1 Docker 无法启动
- 7.2 容器启动后立即退出
- 7.3 ARM64 镜像无法运行
- 7.4 GoWVP 无法连接 ZLMediaKit
- 7.5 GB28181 设备无法接入
- 7.6 性能问题
- 7.7 ARM64 架构稳定性问题(重要)
八、附录
一、文档概述
本手册指导您在可联网的生产环境中,于飞腾S5000C ARM64服务器(统信UOS20操作系统)上完成以下部署:
- GoWVP (Owl): GB28181-2022 标准视频监控管理平台
- ZLMediaKit: 高性能流媒体服务器
- 联动配置: 让 Owl 通过 HTTP API 和 WebHook 调用 ZLMediaKit 的流媒体能力
与离线部署手册的区别:本手册所有操作均在联网的生产服务器上直接执行,无需额外的联网笔记本准备离线包,部署流程更简洁。
1.1 部署架构
┌─────────────────────────────────────────────────────────────┐
│ 监控设备 (摄像头/NVR) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ GB28181 │ │ ONVIF │ │
│ │ 协议接入 │ │ 协议接入 │ │
│ └──────┬───────┘ └──────┬───────┘ │
└─────────────────────┼─────────────────┼──────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ 统信UOS20 服务器 (ARM64) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Docker 容器运行时 │ │
│ │ ┌─────────────────┐ ┌───────────────────────┐ │ │
│ │ │ GoWVP (Owl) │◄──►│ ZLMediaKit │ │ │
│ │ │ 容器 │API │ 流媒体容器 │ │ │
│ │ │ │Hook│ │ │ │
│ │ │ - GB28181 SIP │ │ - RTMP/RTSP/HLS │ │ │
│ │ │ - Web管理界面 │ │ - WebRTC/FLV │ │ │
│ │ │ - 设备管理 │ │ - 录像/转码 │ │ │
│ │ │ - AI检测(YOLO) │ │ │ │ │
│ │ └─────────────────┘ └───────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ 数据持久化卷 │
│ (./data 挂载到容器内的 /opt/media/bin/configs) │
└─────────────────────────────────────────────────────────────┘
1.2 部署方式选择
| 方案 | 说明 | 推荐度 | 适用场景 |
|---|---|---|---|
| 方案A: Docker Compose 融合部署 | 一个docker-compose.yml同时启动owl+ZLMediaKit | ⭐⭐⭐⭐⭐ | 本手册推荐,最简单 |
| 方案B: Docker 分离部署 | 两个独立容器,通过Docker网络通信 | ⭐⭐⭐⭐ | 需要独立升级/维护时 |
| 方案C: 二进制直接部署 | 不依赖Docker,直接运行可执行文件 | ⭐⭐⭐ | 服务器资源极度受限时 |
本手册以方案A(Docker Compose 融合部署)为主,同时提供方案B和C的备用说明。
二、环境说明
2.1 硬件环境
| 项目 | 规格 |
|---|---|
| CPU | 飞腾腾云 S5000C (Phytium S5000C) |
| 指令集 | ARMv8.2 (64位,兼容aarch64) |
| 核心数 | 16核 / 32核 / 64核 (根据采购型号) |
| 主频 | 2.1GHz (64核版) / 2.3GHz (32/16核版) |
| 内存 | 建议 >= 16GB DDR5 |
| 存储 | 建议 >= 500GB SSD (用于录像存储) |
| 网络 | 千兆以太网 (用于GB28181流媒体和Web管理) |
2.2 软件环境
| 项目 | 规格 |
|---|---|
| 操作系统 | 统信UOS服务器版 V20 (1070) |
| 镜像文件名 | uos-server-20-military-1070-20251016-arm64.iso |
| 内核版本 | kernel-4.19 (默认) / kernel-5.10 (可选) |
| 包管理器 | 需确认:可能是 yum(A/E版本) 或 apt(D版本) |
| 架构 | aarch64 / ARM64 |
2.3 统信UOS版本确认方法
在生产环境服务器上执行以下命令确认系统版本:
# 查看操作系统详细信息
cat /etc/os-release
# 查看系统版本标记
cat /etc/system-release 2>/dev/null || cat /etc/centos-release 2>/dev/null || cat /etc/debian_version 2>/dev/null
# 查看包管理器类型
which apt-get && echo "使用 apt (Debian系)"
which yum && echo "使用 yum (RHEL系)"
判断依据:
- 如果看到
Anolis、openEuler、uel20等字样 -> A/E版本,使用yum - 如果看到
Debian、Ubuntu等字样 -> D版本,使用apt - 1070军事版通常基于龙蜥/欧拉,大概率使用
yum/dnf
2.4 网络环境
| 环境 | 网络状态 | 用途 |
|---|---|---|
| 生产服务器 | 可访问互联网 | 下载镜像、安装依赖、部署服务 |
| 网络要求 | 可访问 Docker Hub 或国内镜像仓库 | 拉取 ARM64 容器镜像 |
| 带宽建议 | >= 10Mbps | Docker 镜像总大小约 500MB-1GB |
三、环境初始化
本章节所有操作在生产环境服务器上执行,服务器需保持联网状态。
3.1 确认系统版本和包管理器
# 1. 查看操作系统信息
cat /etc/os-release
# 2. 确认包管理器
which yum && echo "使用 yum" || echo "未安装 yum"
which apt-get && echo "使用 apt" || echo "未安装 apt-get"
# 3. 确认架构
uname -m
# 预期输出: aarch64
# 4. 确认CPU信息
cat /proc/cpuinfo | grep "model name" | head -1
3.2 安装 Docker
3.2.1 通过包管理器安装(推荐)
如果系统使用 yum (A/E版本 - 龙蜥/欧拉):
# 1. 更新系统包(可选,首次部署建议执行)
sudo yum update -y
# 2. 安装必要依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 3. 添加 Docker 官方仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 4. 安装 Docker CE
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 5. 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 6. 验证安装
docker --version
docker-compose --version 2>/dev/null || echo "docker-compose 未安装,将在下一步安装"
如果添加官方仓库失败(部分内网环境限制),可使用统信UOS自带仓库安装:
# 直接使用系统仓库安装 sudo yum install -y docker docker-compose sudo systemctl start docker sudo systemctl enable docker
如果系统使用 apt (D版本 - Debian):
# 1. 更新包索引
sudo apt-get update
# 2. 安装必要依赖
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
# 3. 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 4. 添加 Docker 仓库
echo "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 5. 安装 Docker CE
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 6. 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 7. 验证安装
docker --version
docker compose version
3.2.2 通过静态二进制安装(备用方案)
如果包管理器安装失败,可使用静态二进制:
# 创建临时目录
mkdir -p /tmp/docker-install && cd /tmp/docker-install
# 下载 Docker CE ARM64 静态二进制包
# 推荐版本: 27.5.1 (稳定),也可选择更新的版本
wget https://download.docker.com/linux/static/stable/aarch64/docker-27.5.1.tgz
# 解压并安装
tar -xzf docker-27.5.1.tgz
sudo cp -p docker/* /usr/bin/
# 下载 Docker Compose ARM64
sudo wget -O /usr/bin/docker-compose https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-linux-aarch64
sudo chmod +x /usr/bin/docker-compose
# 创建 systemd 服务
sudo tee /etc/systemd/system/docker.service > /dev/null << 'EOF'
[Unit]
Description=Docker Application Container Engine
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# 启动 Docker
sudo systemctl daemon-reload
sudo systemctl start docker
sudo systemctl enable docker
# 验证
docker --version
docker-compose --version
3.3 配置 Docker 国内镜像加速(推荐)
由于 Docker Hub 在国内访问不稳定,建议配置镜像加速器:
# 创建/编辑 Docker 守护进程配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
EOF
# 重启 Docker 使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证加速器是否生效
docker info | grep -A 5 "Registry Mirrors"
注意: 以上加速器地址可能会变更,如失效请搜索最新可用地址。 在部分涉密/军用网络环境中,可能无法访问公共镜像仓库,此时需要联系网络管理员获取内部镜像仓库地址。
3.4 安装常用工具
# yum 系统
sudo yum install -y wget curl vim net-tools telnet htop
# apt 系统
sudo apt-get install -y wget curl vim net-tools telnet htop
3.5 创建部署目录
# 创建部署根目录
sudo mkdir -p /opt/owl-zlmediakit
cd /opt/owl-zlmediakit
# 创建数据持久化目录
sudo mkdir -p /data/owl-zlm/record /data/owl-zlm/log /data/owl-zlm/gowvp-configs /data/owl-zlm/snap
sudo chmod -R 755 /data/owl-zlm/
# 查看目录结构
ls -la
四、服务部署
4.1 拉取 Docker 镜像
# 拉取 ZLMediaKit 官方 ARM64 镜像
docker pull zlmediakit/zlmediakit:master
# 拉取 GoWVP (Owl) 官方 ARM64 镜像
docker pull gospace/gowvp:latest
# 验证镜像架构(必须显示 "arm64")
docker inspect zlmediakit/zlmediakit:master | grep Architecture
# 预期输出: "Architecture": "arm64"
docker inspect gospace/gowvp:latest | grep Architecture
# 预期输出: "Architecture": "arm64"
# 查看已下载镜像
docker images | grep -E "zlmediakit|gowvp"
国内网络加速(如拉取缓慢或失败):
# 方案A: 使用华为云镜像加速 ZLMediaKit
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/zlmediakit/zlmediakit:master-linuxarm64
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/zlmediakit/zlmediakit:master-linuxarm64 zlmediakit/zlmediakit:master
# 方案B: 使用阿里云镜像加速 GoWVP
docker pull registry.cn-shanghai.aliyuncs.com/ixugo/homenvr:latest
docker tag registry.cn-shanghai.aliyuncs.com/ixugo/homenvr:latest gospace/gowvp:latest
重要提醒: 即使服务器是 ARM64 架构,也建议通过
docker inspect确认镜像架构为arm64,避免意外拉取到多架构镜像中的错误版本。
4.2 准备配置文件
4.2.1 IP 地址配置说明(重要)
在编辑配置文件前,请确认以下IP地址使用规则:
| 配置项 | 当前值 | 用途 | 修改建议 |
|---|---|---|---|
GOWVP_ZLM_HOST |
192.168.3.108 |
GoWVP向外部返回的流媒体地址 | 必须改为服务器实际IP,否则外部设备/浏览器无法访问 |
externIP |
192.168.3.108 |
WebRTC外部访问IP | 必须改为服务器实际IP,否则WebRTC无法穿透 |
| Hook回调地址 | 127.0.0.1 |
ZLMediaKit回调GoWVP的内部接口 | 保持127.0.0.1,两者在同一服务器的host网络模式下,本机通信无需暴露 |
为什么GOWVP_ZLM_HOST不能用127.0.0.1?
- GoWVP在生成播放地址(如FLV、HLS、WebRTC链接)时,会将此地址返回给浏览器或设备
- 如果返回
http://127.0.0.1:80/xxx,浏览器会在用户本机寻找服务器,显然找不到- 必须返回
http://192.168.3.108:80/xxx,外部设备才能正确访问
为什么Hook回调可以保持127.0.0.1?
- Hook是ZLMediaKit主动调用GoWVP的内部通知机制
- 两者都使用
network_mode: host,共享服务器的网络栈- ZLMediaKit在服务器上访问
127.0.0.1:15123,就是访问同一台服务器上的GoWVP,完全正确
如果您的服务器IP不是192.168.3.108,请务必修改以下两个配置:
# 获取服务器实际IP(用于替换配置中的IP)
SERVER_IP=$(hostname -I | awk '{print $1}')
echo "服务器IP: ${SERVER_IP}"
4.2.2 创建 docker-compose.yml
创建文件 /opt/owl-zlmediakit/docker-compose.yml:
cd /opt/owl-zlmediakit
sudo tee docker-compose.yml > /dev/null << 'EOF'
version: '3.8'
services:
# ZLMediaKit 流媒体服务
zlmediakit:
image: zlmediakit/zlmediakit:master
container_name: zlmediakit
restart: always
privileged: true
network_mode: host
volumes:
- ./data/zlm-config.ini:/opt/media/conf/config.ini:ro
- ./data/record:/opt/media/bin/www/record
- ./data/log:/opt/media/bin/log
environment:
- TZ=Asia/Shanghai
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
# GoWVP (Owl) 管理平台
gowvp:
image: gospace/gowvp:latest
container_name: gowvp
restart: always
network_mode: host
depends_on:
- zlmediakit
volumes:
- ./data/gowvp-configs:/opt/media/bin/configs
- ./data/record:/opt/media/bin/www/record
environment:
- TZ=Asia/Shanghai
# 必须使用服务器实际IP,不能填127.0.0.1
# 原因:GoWVP向浏览器/设备返回的流媒体播放地址会包含此IP
- GOWVP_ZLM_HOST=192.168.3.108
- GOWVP_ZLM_PORT=80
- GOWVP_ZLM_SECRET=035c73f7-bb6b-4889-a715-d9eb2d1925cc
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
EOF
注意: 如果服务器IP不是
192.168.3.108,请将GOWVP_ZLM_HOST修改为实际IP。
4.2.3 创建 ZLMediaKit 配置文件
创建文件 /opt/owl-zlmediakit/data/zlm-config.ini:
cd /opt/owl-zlmediakit
sudo tee data/zlm-config.ini > /dev/null << 'EOF'
; ZLMediaKit 配置文件
; 针对 ARM64 + 联网环境优化
[api]
apiDebug=1
secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc
snapRoot=./www/snap/
defaultSnap=./www/logo.png
downloadRoot=./www
[ffmpeg]
bin=/usr/bin/ffmpeg
cmd=%s -re -i %s -c copy -f flv %s
snap=%s -i %s -y -f mjpeg -t 0.001 %s
[general]
enableVhost=0
flowThreshold=1024
maxStreamWaitMS=15000
streamNoneReaderDelayMS=20000
resetWhenRePlay=1
mergeWriteMS=0
mediaServerId=owl-zlm-server-01
wait_add_track_ms=3000
wait_track_ready_ms=10000
[hls]
fileBufSize=65536
segDur=2
segNum=3
segRetain=5
broadcastRecordTs=0
fastRegister=0
[hook]
enable=1
on_publish=https://127.0.0.1:15123/api/v1/hook/on_publish
on_play=https://127.0.0.1:15123/api/v1/hook/on_play
on_stream_not_found=https://127.0.0.1:15123/api/v1/hook/on_stream_not_found
on_server_started=https://127.0.0.1:15123/api/v1/hook/on_server_started
on_server_keepalive=https://127.0.0.1:15123/api/v1/hook/on_server_keepalive
on_send_rtp_stopped=https://127.0.0.1:15123/api/v1/hook/on_send_rtp_stopped
on_rtp_server_timeout=https://127.0.0.1:15123/api/v1/hook/on_rtp_server_timeout
admin_params=secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc
timeoutSec=20
[http]
charSet=utf-8
keepAliveSecond=30
maxReqSize=40960
notFound=<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>您访问的资源不存在!</h1></center><hr><center>ZLMediaKit-4.0</center></body></html>
port=80
rootPath=./www
sendBufSize=65536
sslport=443
virtualPath=
[multicast]
addrMax=239.255.255.255
addrMin=239.0.0.0
udpTTL=64
[record]
appName=record
fastStart=0
fileBufSize=65536
fileSecond=3600
sampleMS=500
[rtmp]
directProxy=1
enhanced=0
handshakeSecond=15
keepAliveSecond=15
port=1935
[rtp]
audioMtuSize=600
h264_stap_a=1
opus_rtp_ext=0
rtpMaxSize=10
videoMtuSize=1400
[rtp_proxy]
dumpDir=
port=10000
port_range=30000-30500
[rtsp]
authBasic=0
directProxy=1
handshakeSecond=15
keepAliveSecond=15
port=554
sslport=332
[srt]
latencyMul=4
pktBufSize=8192
port=9000
timeoutSec=5
[rtc]
# WebRTC外部IP,必须设置为服务器实际IP,否则外部浏览器无法播放
externIP=192.168.3.108
port=8000
tcpPort=8000
rembBitRate=0
[shell]
maxReqSize=1024
port=9000
[cluster]
origin_url=
retry_count=3
timeout_sec=15
EOF
4.3 启动服务
cd /opt/owl-zlmediakit
# 首次启动建议前台运行,观察日志确认无错误
docker-compose up
# 如果日志显示服务正常启动,按 Ctrl+C 停止前台运行
# 然后后台启动
docker-compose up -d
# 查看运行状态
docker-compose ps
# 查看 ZLMediaKit 日志
docker logs -f zlmediakit
# 查看 GoWVP 日志
docker logs -f gowvp
启动成功标志:
docker-compose ps显示两个容器状态为Up- ZLMediaKit 日志显示
MediaServer已启动,监听端口无报错 - GoWVP 日志显示 Web 服务已启动,端口 15123 监听正常
4.4 部署 ZLMediaKit(单独运行方式)
如果使用 Docker Compose 融合部署,此节可跳过。本节仅用于单独部署 ZLMediaKit 的场景。
# 单独运行 ZLMediaKit 容器
docker run -id \
--name zlmediakit \
--restart always \
--privileged \
--network host \
-v /opt/owl-zlmediakit/data/zlm-config.ini:/opt/media/conf/config.ini:ro \
-v /opt/owl-zlmediakit/data/record:/opt/media/bin/www/record \
-v /opt/owl-zlmediakit/data/log:/opt/media/bin/log \
-e TZ=Asia/Shanghai \
zlmediakit/zlmediakit:master
# 查看日志
docker logs -f zlmediakit
4.5 部署 GoWVP(Owl)(单独运行方式)
如果使用 Docker Compose 融合部署,此节可跳过。
# 单独运行 GoWVP 容器
docker run -id \
--name gowvp \
--restart always \
--network host \
-v /opt/owl-zlmediakit/data/gowvp-configs:/opt/media/bin/configs \
-v /opt/owl-zlmediakit/data/record:/opt/media/bin/www/record \
-e TZ=Asia/Shanghai \
-e GOWVP_ZLM_HOST=192.168.3.108 \
-e GOWVP_ZLM_PORT=80 \
-e GOWVP_ZLM_SECRET=035c73f7-bb6b-4889-a715-d9eb2d1925cc \
gospace/gowvp:latest
# 查看日志
docker logs -f gowvp
五、配置联动
GoWVP 与 ZLMediaKit 的联动已通过以下方式配置完成:
- ZLMediaKit Hook 回调: ZLMediaKit 在流注册、播放、推流等事件发生时,通过 HTTP POST 请求通知 GoWVP
- GoWVP RESTful API: GoWVP 通过 ZLMediaKit 的 HTTP API 控制流的拉取、转码、录制等操作
- 共享存储: 两个容器通过 bind mount 共享
./data/record目录,用于录像文件存储
5.1 ZLMediaKit Hook 配置
上述 zlm-config.ini 中已包含 Hook 配置:
[hook]
enable=1
on_publish=https://127.0.0.1:15123/api/v1/hook/on_publish
on_play=https://127.0.0.1:15123/api/v1/hook/on_play
on_stream_not_found=https://127.0.0.1:15123/api/v1/hook/on_stream_not_found
on_server_started=https://127.0.0.1:15123/api/v1/hook/on_server_started
on_server_keepalive=https://127.0.0.1:15123/api/v1/hook/on_server_keepalive
on_send_rtp_stopped=https://127.0.0.1:15123/api/v1/hook/on_send_rtp_stopped
on_rtp_server_timeout=https://127.0.0.1:15123/api/v1/hook/on_rtp_server_timeout
admin_params=secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc
timeoutSec=20
5.2 GoWVP 环境变量配置
上述 docker-compose.yml 中已包含环境变量配置:
environment:
- GOWVP_ZLM_HOST=192.168.3.108 # ZLMediaKit 地址(必须使用服务器实际IP)
- GOWVP_ZLM_PORT=80 # ZLMediaKit HTTP端口
- GOWVP_ZLM_SECRET=035c73f7-bb6b-4889-a715-d9eb2d1925cc # API密钥
关于 GOWVP_ZLM_HOST 必须使用实际IP的说明:
- 此IP用于GoWVP生成对外播放地址(如FLV、HLS、WebRTC链接)
- 如果填
127.0.0.1,浏览器会尝试连接用户本地电脑,导致播放失败- 如果服务器有多个网卡/IP,建议填写摄像头/用户浏览器可访问的那个IP
如需修改配置:编辑
data/zlm-config.ini或docker-compose.yml后,执行docker-compose restart使配置生效。
5.3 重启服务使配置生效
cd /opt/owl-zlmediakit
docker-compose restart
# 等待30秒后检查状态
sleep 30
docker-compose ps
5.4 联动验证
# 查看 ZLMediaKit 日志,确认 Hook 回调成功
docker logs zlmediakit | grep -i "hook"
# 查看 GoWVP 日志,确认收到 ZLMediaKit 事件
docker logs gowvp | grep -i "zlm\|hook"
六、验证步骤
6.1 验证脚本
创建并运行验证脚本:
cd /opt/owl-zlmediakit
# 创建验证脚本
sudo tee scripts/verify.sh > /dev/null << 'EOF'
#!/bin/bash
# GoWVP + ZLMediaKit 部署验证脚本
set -e
SERVER_IP=$(hostname -I | awk '{print $1}')
ZLM_SECRET="035c73f7-bb6b-4889-a715-d9eb2d1925cc"
echo "=========================================="
echo " GoWVP + ZLMediaKit 部署验证"
echo " 服务器IP: ${SERVER_IP}"
echo "=========================================="
# 1. 检查 Docker 状态
echo -e "\n[1/6] 检查 Docker 状态..."
if systemctl is-active --quiet docker; then
echo " ✓ Docker 运行正常"
else
echo " ✗ Docker 未运行"
exit 1
fi
# 2. 检查容器状态
echo -e "\n[2/6] 检查容器状态..."
if docker ps | grep -q zlmediakit; then
echo " ✓ ZLMediaKit 容器运行中"
else
echo " ✗ ZLMediaKit 容器未运行"
exit 1
fi
if docker ps | grep -q gowvp; then
echo " ✓ GoWVP 容器运行中"
else
echo " ✗ GoWVP 容器未运行"
exit 1
fi
# 3. 测试 ZLMediaKit API
echo -e "\n[3/6] 测试 ZLMediaKit API..."
if curl -s "http://${SERVER_IP}/index/api/getApiList" > /dev/null; then
echo " ✓ ZLMediaKit API 响应正常"
else
echo " ✗ ZLMediaKit API 无响应"
fi
# 4. 测试获取流列表
echo -e "\n[4/6] 测试获取媒体流列表..."
if curl -s "http://${SERVER_IP}/index/api/getMediaList?secret=${ZLM_SECRET}" > /dev/null; then
echo " ✓ 媒体流列表接口正常"
else
echo " ✗ 媒体流列表接口异常"
fi
# 5. 测试 GoWVP Web 服务
echo -e "\n[5/6] 测试 GoWVP Web 服务..."
if curl -s -I "http://${SERVER_IP}:15123" | grep -q "200\|302"; then
echo " ✓ GoWVP Web 服务响应正常"
else
echo " ✗ GoWVP Web 服务无响应"
fi
# 6. 检查端口监听
echo -e "\n[6/6] 检查关键端口..."
for port in 80 15123 15060 1935 554; do
if netstat -tlnp 2>/dev/null | grep -q ":${port} " || ss -tlnp 2>/dev/null | grep -q ":${port} "; then
echo " ✓ 端口 ${port} 监听正常"
else
echo " ✗ 端口 ${port} 未监听"
fi
done
echo -e "\n=========================================="
echo " 验证完成"
echo " ZLMediaKit: http://${SERVER_IP}"
echo " GoWVP: http://${SERVER_IP}:15123"
echo "=========================================="
EOF
sudo chmod +x scripts/verify.sh
# 运行验证脚本
sudo ./scripts/verify.sh
6.2 手动验证步骤
6.2.1 验证 ZLMediaKit
# 获取服务器IP
SERVER_IP=$(hostname -I | awk '{print $1}')
# 测试 ZLMediaKit API
curl "http://${SERVER_IP}/index/api/getApiList"
# 测试获取流列表
curl "http://${SERVER_IP}/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc"
# 在浏览器中访问
# http://<服务器IP>
6.2.2 验证 GoWVP
# 测试 GoWVP Web 界面
curl -I "http://${SERVER_IP}:15123"
# 在浏览器中访问管理界面
# http://<服务器IP>:15123
# 默认账号密码请查看 GoWVP 官方文档
6.2.3 验证 GB28181 端口
# 检查 SIP 端口(UDP/TCP 15060)
netstat -ulnp | grep 15060
netstat -tlnp | grep 15060
# 检查流媒体端口范围(20000-20100)
netstat -ulnp | grep -E "20000|20001|20002"
6.3 推流测试
如果您有支持 RTMP/RTSP 的摄像头或推流工具,可以进行测试:
# RTMP 推流测试地址(使用FFmpeg)
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://<服务器IP>/live/test
# 播放测试
# RTMP: rtmp://<服务器IP>/live/test
# HLS: http://<服务器IP>/live/test/hls.m3u8
# FLV: http://<服务器IP>/live/test.live.flv
七、常见问题排查
7.1 Docker 无法启动
现象: systemctl start docker 失败
排查步骤:
# 查看详细错误
journalctl -u docker -n 50
# 检查内核是否支持容器
cat /proc/1/cgroup
# 手动运行dockerd查看错误
/usr/bin/dockerd
解决方案:
- 确保内核版本 >= 3.10(统信UOS kernel-4.19 满足要求)
- 检查
/var/run/docker.sock权限 - 确保
iptables可用:which iptables - 检查 SELinux 状态:
getenforce,如为 Enforcing 可尝试临时关闭:setenforce 0
7.2 容器启动后立即退出
现象: docker ps 看不到运行的容器
排查步骤:
# 查看容器退出日志
docker logs zlmediakit
docker logs gowvp
# 查看容器状态
docker ps -a
docker inspect zlmediakit
常见原因:
- 端口被占用:
netstat -tlnp | grep :80 - 配置文件路径错误:检查 volume 映射
- 权限不足:确保使用
--privileged或正确配置 capabilities
7.3 ARM64 镜像无法运行
现象: 报错 exec format error
原因: 镜像架构与服务器不匹配(拉取了 x86_64 镜像)
解决方案:
# 检查镜像架构
docker inspect zlmediakit/zlmediakit:master | grep Architecture
# 必须显示 "arm64"
# 如果错误,删除错误镜像并重新拉取
docker rmi zlmediakit/zlmediakit:master
docker pull --platform linux/arm64 zlmediakit/zlmediakit:master
7.4 GoWVP 无法连接 ZLMediaKit
现象: GoWVP 日志显示连接 ZLMediaKit 失败
排查步骤:
# 检查 ZLMediaKit 是否正常运行
curl http://127.0.0.1/index/api/getApiList
# 检查 secret 是否一致
grep secret data/zlm-config.ini
grep GOWVP_ZLM_SECRET docker-compose.yml
# 检查 Hook 配置是否正确
grep "on_publish\|on_play" data/zlm-config.ini
7.5 GB28181 设备无法接入
现象: 摄像头无法注册到 GoWVP
排查步骤:
# 检查 SIP 端口是否监听
netstat -ulnp | grep 15060
# 检查防火墙
firewall-cmd --list-ports # 如果使用 firewalld
iptables -L -n | grep 15060
# 查看 GoWVP 日志
docker logs -f gowvp | grep -i "sip\|register"
必要端口清单:
| 端口 | 协议 | 用途 |
|---|---|---|
| 80 | TCP | HTTP/Web |
| 443 | TCP | HTTPS |
| 15123 | TCP | GoWVP Web管理 |
| 15060 | UDP/TCP | GB28181 SIP |
| 1935 | TCP | RTMP |
| 554 | TCP | RTSP |
| 8000 | UDP/TCP | WebRTC |
| 9000 | UDP | SRT |
| 10000 | UDP | RTP代理 |
| 20000-20100 | UDP | GB28181 媒体流 |
| 30000-30500 | UDP | RTP端口范围 |
7.6 性能问题
现象: 视频卡顿、延迟高
优化建议:
# 查看CPU和内存使用情况
top
htop
# 查看磁盘IO
iostat -x 1
# ZLMediaKit 配置优化:关闭转码以节省CPU
# 在 config.ini 中:
[ffmpeg]
cmd=%s -re -i %s -c copy -f flv %s # 使用 copy 而不是重新编码
# 限制日志大小避免磁盘占满
docker system prune -f
7.7 ARM64 架构稳定性问题(重要)
⚠️ 本章节针对飞腾S5000C等ARM64服务器的重要风险提示
7.7.1 已知问题概述
GitHub Issue: #3466 - In ARM architecture, ZLM live streaming is unstable
问题描述: ZLMediaKit 在 ARM64 (aarch64) 架构下运行 GB28181 RTP 推流时,存在偶发性崩溃问题,x86_64 架构下相同配置稳定运行。
7.7.2 具体症状
| 症状 | 描述 |
|---|---|
| 进程崩溃 | MediaServer 进程意外退出,Docker 容器重启 |
| Signal 11 | 收到 SIGSEGV (段错误),内存访问违规 |
| 流中断 | GB28181 RTP 推流频繁断开,需重新注册 |
| 错误日志 | Unsupported codec: PCMU、Unsupported codec: invalid |
典型错误日志:
2024-04-11 07:13:07.002 W [MediaServer] [319-event poller 3] Factory.cpp:118 getTrackByCodecId | Unsupported codec: PCMU
2024-04-11 07:13:24.885 W [MediaServer] [319-event poller 3] Factory.cpp:200 getFrameFromPtr | Unsupported codec: invalid
崩溃堆栈特征(简化):
Signal 11 received
Stacktrace:
FrameCacheAble::FrameCacheAble(...)
Factory::getFrameFromBuffer(...)
FrameMerger::inputFrame(...)
FrameMerger::flush(...)
DecoderImp::flush(...)
RtpProcessHelper::~RtpProcessHelper()
崩溃位置分析: 堆栈显示崩溃发生在帧缓存分配和解码器刷新阶段,疑似与内存对齐或并发访问有关。
7.7.3 可重现性
| 条件 | 可重现性 |
|---|---|
| Docker 部署 + ARM64 | 高 - 社区多个用户报告 |
| 物理机/虚拟机 ARM64 | 中 - 部分用户报告 |
| x86_64 (相同配置) | 无法重现 - 稳定运行 |
| GB28181 RTP 推流 | 高 - 主要触发场景 |
| RTMP/RTSP 推流 | 低 - 偶发 |
| 空闲状态 | 无 - 仅在活跃推流时 |
7.7.4 可能原因分析
- 内存对齐问题: ARM64 架构对内存对齐要求更严格,某些数据结构在 x86 上能正常工作但在 ARM 上触发 SIGSEGV
- 并发访问竞争: FrameMerger 在多线程环境下可能存在 race condition
- Codec 解析异常: 某些摄像头发送的 PS 流格式不规范,ARM 版解码器处理异常时未正确保护
- Docker 环境差异: Docker 在 ARM64 上的 QEMU 模拟或 seccomp 策略可能影响行为
7.7.5 规避方案与解决方案
方案一:使用官方最新镜像(推荐尝试)
# 确保使用最新 master 分支镜像,可能已修复
# 官方维护者持续在修复 ARM64 相关问题
docker pull zlmediakit/zlmediakit:master
docker inspect zlmediakit/zlmediakit:master | grep -E "Created|Revision"
方案二:启用容器自动重启
# 在 docker-compose.yml 中已配置 restart: always
# 崩溃后容器会自动重启,业务中断时间 < 10 秒
services:
zlmediakit:
restart: always
# 可选:增加重启策略
deploy:
restart_policy:
condition: any
delay: 5s
max_attempts: 10
方案三:限制单路流的并发处理
# 在 config.ini 中降低并发处理线程数
[general]
# 减少事件轮询线程数(默认等于 CPU 核心数)
# 可尝试设置为物理核心数的一半
# 注意: 此配置需查阅最新文档确认参数名
[ffmpeg]
# 关闭转码,减少编解码压力
cmd=%s -re -i %s -c copy -f flv %s
方案四:使用 host 网络模式(已默认配置)
# docker-compose.yml 中已配置 network_mode: host
# 避免 Docker 桥接网络在 ARM64 上的性能开销和潜在 bug
services:
zlmediakit:
network_mode: host
方案五:监控并自动恢复
# 创建监控脚本 /opt/owl-zlmediakit/scripts/monitor.sh
sudo tee /opt/owl-zlmediakit/scripts/monitor.sh > /dev/null << 'EOF'
#!/bin/bash
while true; do
if ! docker ps | grep -q zlmediakit; then
echo "$(date): ZLMediaKit 容器异常,正在重启..." >> /var/log/zlm-monitor.log
cd /opt/owl-zlmediakit && docker-compose restart zlmediakit
fi
sleep 10
done
EOF
sudo chmod +x /opt/owl-zlmediakit/scripts/monitor.sh
# 使用 systemd 或 screen 后台运行监控脚本
# 或使用 systemd 定时任务
方案六:源码编译(终极方案)
# 如果 Docker 镜像问题持续,可在 ARM64 服务器上本地编译
# 本地编译会针对具体 CPU 指令集优化,可能规避问题
cd /usr/src/ZLMediaKit
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-faligned-new"
make -j$(nproc)
7.7.6 生产环境建议
| 场景 | 建议 |
|---|---|
| 测试/开发环境 | 可直接使用 Docker 部署,观察稳定性 |
| 生产环境(关键业务) | 强烈建议先进行 7x24 小时压力测试,确认无崩溃后再上线 |
| 已出现崩溃 | 启用自动重启 + 监控脚本,同时向 ZLMediaKit GitHub 提交 issue |
| 追求极致稳定 | 考虑在 ARM64 上源码编译,或改用 x86_64 服务器部署 ZLMediaKit |
7.7.7 社区状态跟踪
- Issue 状态: Closed (因未按模板提交被关闭,但问题真实存在)
- 社区反馈: 多名用户确认在 RK3568、树莓派、鲲鹏等 ARM64 设备上遇到类似问题
- 官方态度: 维护者表示会持续关注 ARM64 兼容性,建议用户使用最新版本
- 建议操作: 如遇到崩溃,请收集完整堆栈和复现步骤,向 ZLMediaKit Issues 提交反馈
7.7.8 相关 Issue 深度分析
以下三个 Issue 与 ARM64 稳定性密切相关,建议主人一并了解。
Issue #3202 - RK3588 SIGABRT 崩溃
| 项目 | 详情 |
|---|---|
| 硬件 | RK3588 (Ubuntu 20.04.6) |
| 信号 | SIGABRT (signal 6) |
| 版本 | git hash e593ef5/2023-12-17 |
| 触发条件 | 视频流不稳定时持续崩溃 |
崩溃堆栈特征:
[0]: MediaServer(+0x992ba8)
[4]: libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x188)
[8]: MediaServer(Assert_Throw+0x184)
根本原因(官方维护者 @xia-chu 回复):
"这个不算bug,是你的编译器默认关闭了异常功能,一抛异常就默认 abort。编译器开启异常功能需要加上编译选项
-fexceptions。"
技术解释:
- ARM 交叉编译工具链(如
aarch64-linux-gnu-gcc)默认关闭 C++ 异常处理 - 当 ZLMediaKit 内部抛出 C++ 异常(如
Assert_Throw失败)时,libstdc++ 的 terminate handler 被调用 - 由于异常被禁用,该 handler 直接调用
abort()导致进程终止
解决方案:
# 在 CMakeLists.txt 中添加
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
endif()
或在 cmake 命令中指定:
cmake .. -DCMAKE_CXX_FLAGS="-fexceptions"
⚠️ 重要:
-fexceptions是 GCC 标准选项,不是临时 hack。ZLMediaKit 大量使用 C++ 异常,在 ARM 上编译必须显式启用。
Issue #2728 - ARM 内存"泄漏"问题
| 项目 | 详情 |
|---|---|
| 平台 | ARM (aarch64), Ubuntu 18, 内存 4G |
| 现象 | 调用 getStatisticJson 接口时系统卡死;开启 ENABLE_MEM_DEBUG 后机器完全卡住 |
| 本质 | 内存碎片,非真正泄漏 |
详细分析:
-
内存碎片问题:
- ZLMediaKit 调用
free()将内存返还给 glibc 的 ptmalloc - 但 ptmalloc 不会立即将内存返还给操作系统(出于性能考虑)
- 导致
RSS内存居高不下,看起来像泄漏
- ZLMediaKit 调用
-
ENABLE_MEM_DEBUG的陷阱:# ZLMediaKit 使用链接器 wrap 机制拦截内存分配 if(ENABLE_MEM_DEBUG) update_cached_list(MK_LINK_LIBRARIES "-Wl,-wrap,free;-Wl,-wrap,malloc;-Wl,-wrap,realloc;-Wl,-wrap,calloc") endif()- 在 ARM 平台上,
-Wl,-wrap拦截每次 malloc/free,性能开销极大 - 高并发场景下会导致系统完全卡死
- 生产环境切勿开启 ENABLE_MEM_DEBUG
- 在 ARM 平台上,
-
解决方案 - 使用 tcmalloc:
# 编译时启用 tcmalloc cmake .. -DENABLE_TCMALLOC=ON- tcmalloc 采用 per-CPU 缓存 机制,更好地管理内存碎片
- 在 RTP 断流重连场景下,内存可以稳定复用
tcmalloc 静态库编译注意事项:
# 编译 gperftools 时需要加 -fPIC ./configure CFLAGS="-fPIC" CXXFLAGS="-fPIC" make运行时加载:
LD_PRELOAD=libtcmalloc.so.4 ./MediaServer -
替代方案 - jemalloc:
# ZLMediaKit 默认优先链接 jemalloc find_package(JEMALLOC QUIET) if(JEMALLOC_FOUND) update_cached_list(MK_LINK_LIBRARIES ${JEMALLOC_LIBRARIES}) add_definitions(-DUSE_JEMALLOC) endif()
Issue #2043 - RK3568 拉流断开问题
| 项目 | 详情 |
|---|---|
| 硬件 | RK3568 |
| 信号 | SIGSEGV (signal 11) |
| 版本 | git hash b3fd74c |
| 触发条件 | 拉流后很快断开 |
错误日志:
## signal: 11
[0]: ./MediaServer() [0x995710] sig_crash(int)
[1]: /lib/arm-linux-gnueabihf/libc.so.6(+0x25260)
可能原因:
- RK 系列网卡驱动 bug(与 RK3399 类似)
"rk3339 的网卡驱动是有 bug 的!如果是从上面往别处 tcp 发送大的数据包,在 tcp 的 ip 数据报分片以后会出现校验和计算错误"
- 交叉编译环境配置问题
- 缺少必要的系统库
状态: Issue 已关闭,标题显示"问题已经解决,谢谢",但未详细说明解决方案。
建议: 如遇到类似问题,优先尝试:
- 更新到最新代码
- 检查网卡驱动版本
- 在 GDB 下调试获取完整堆栈
7.7.9 ARM64 编译优化建议
必加编译选项:
| 选项 | 用途 | 必要性 |
|---|---|---|
-fexceptions |
启用 C++ 异常处理 | 必须 |
-pthread |
线程支持 | 必须 |
-fPIC |
位置无关代码(动态库需要) | 推荐 |
-faligned-new |
对齐内存分配 | 推荐 |
完整编译命令示例:
cd /usr/src/ZLMediaKit
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC -faligned-new" \
-DENABLE_WEBRTC=ON \
-DENABLE_FFMPEG=ON \
-DENABLE_TCMALLOC=ON
make -j$(nproc)
交叉编译示例(飞腾S5000C):
# 创建工具链文件 /tmp/toolchain.cmake
cat > /tmp/toolchain.cmake << 'EOF'
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
EOF
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=/tmp/toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC" \
-DENABLE_TCMALLOC=ON
make -j$(nproc)
7.7.10 官方态度与未来展望
官方维护者 (@xia-chu) 的态度:
- 承认 ARM64 支持,但认为问题多源于用户环境/编译方式
- 对于崩溃问题,往往归结为:端口占用、编译器选项问题 (
-fexceptions)、Android 限制等 - 没有看到系统性的 ARM64 修复计划公告
已有的 ARM64 修复:
- PR #2479 (2023-05): 修复 ARM 内存对齐问题
- Commit
7cb772c: "On arm need align, without this the application crashed after SIGBUS"
- Commit
- PR #2800 (2023-08): 修复
close_stream与getMediaList并发崩溃 - PR #4582 (2025-12): 修复 RtspSession/RtspPusher 空指针崩溃
未来计划:
- 2024 年 12 月,@xia-chu 表示:"后面我会考虑添加下 arm64 的 ci 自动编译并发布二进制包"
- 但截至 2026 年 4 月,尚未实现 ARM64 CI 自动编译和二进制发布
Issue #483 预编译二进制包:
- 这是官方发布预编译二进制的位置
- 目前仅有 macOS ARM64 包,Linux ARM64 包链接已失效
- 下载地址: https://github.com/ZLMediaKit/ZLMediaKit/issues/483
八、附录
附录A: 端口清单
| 端口 | 协议 | 服务 | 说明 |
|---|---|---|---|
| 80 | TCP | ZLMediaKit | HTTP 服务 |
| 443 | TCP | ZLMediaKit | HTTPS 服务 |
| 15123 | TCP | GoWVP | Web 管理界面 |
| 15060 | UDP/TCP | GoWVP | GB28181 SIP 信令 |
| 1935 | TCP | ZLMediaKit | RTMP 推流/播放 |
| 554 | TCP | ZLMediaKit | RTSP 服务 |
| 8000 | UDP/TCP | ZLMediaKit | WebRTC |
| 9000 | UDP | ZLMediaKit | SRT 协议 |
| 10000 | UDP | ZLMediaKit | RTP 代理 |
| 20000-20100 | UDP | GoWVP | GB28181 媒体流传输 |
| 30000-30500 | UDP | ZLMediaKit | RTP 端口范围 |
附录B: 源码编译 ZLMediaKit(备用方案)
如果 Docker 方案不可用或需要针对飞腾S5000C优化,可以选择源码编译:
# 1. 安装编译依赖
# yum 系统:
sudo yum install -y gcc gcc-c++ cmake git openssl-devel
# apt 系统:
sudo apt-get install -y build-essential cmake git libssl-dev
# 2. 下载源码(联网环境直接克隆)
cd /usr/src
sudo git clone --depth 1 https://github.com/ZLMediaKit/ZLMediaKit.git
cd ZLMediaKit
sudo git submodule update --init --recursive
# 3. 编译(针对 ARM64 添加必要参数)
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC -faligned-new" \
-DENABLE_WEBRTC=ON \
-DENABLE_FFMPEG=ON \
-DENABLE_TCMALLOC=ON
make -j$(nproc)
# 4. 运行
sudo ./release/linux/Release/MediaServer -d &
注意: WebRTC 功能需要 libsrtp 2.5.0,编译前请确保已安装。
附录C: 源码编译 GoWVP(备用方案)
# 1. 安装 Go 环境(1.20+)
# 下载 ARM64 版本 Go
cd /tmp
wget https://go.dev/dl/go1.22.0.linux-arm64.tar.gz
sudo tar -C /usr/local -xzf go1.22.0.linux-arm64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# 2. 下载并编译 GoWVP
cd /usr/src
git clone https://github.com/gowvp/owl.git
cd owl
make build
# 3. 运行
./bin/owl-server &
或者使用预编译二进制(联网环境可直接下载):
wget https://github.com/gowvp/owl/releases/download/v1.3.0/owl_linux_arm64.tar.gz tar xzf owl_linux_arm64.tar.gz -C /usr/local/ /usr/local/owl/owl-server &
附录D: 防火墙配置
# 如果使用 firewalld
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=15123/tcp
sudo firewall-cmd --permanent --add-port=15060/tcp
sudo firewall-cmd --permanent --add-port=15060/udp
sudo firewall-cmd --permanent --add-port=1935/tcp
sudo firewall-cmd --permanent --add-port=554/tcp
sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --permanent --add-port=8000/udp
sudo firewall-cmd --permanent --add-port=9000/udp
sudo firewall-cmd --permanent --add-port=10000/udp
sudo firewall-cmd --permanent --add-port=20000-20100/udp
sudo firewall-cmd --permanent --add-port=30000-30500/udp
sudo firewall-cmd --reload
# 如果使用 iptables
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 15123 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 15060 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 15060 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 1935 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 554 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 8000 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 8000 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 9000 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 10000 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 20000:20100 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 30000:30500 -j ACCEPT
附录E: 参考链接
| 资源 | 地址 |
|---|---|
| ZLMediaKit GitHub | https://github.com/ZLMediaKit/ZLMediaKit |
| ZLMediaKit 文档 | https://docs.zlmediakit.com/ |
| ZLMediaKit Docker Hub | https://hub.docker.com/r/zlmediakit/zlmediakit |
| GoWVP (Owl) GitHub | https://github.com/gowvp/owl |
| GoWVP Docker Hub | https://hub.docker.com/r/gospace/gowvp |
| Docker CE 下载 | https://download.docker.com/linux/static/stable/aarch64/ |
| Docker Compose 下载 | https://github.com/docker/compose/releases |
| libsrtp 下载 | https://github.com/cisco/libsrtp/releases |
附录F: ARM64 架构问题速查表
本附录汇总 ZLMediaKit 在 ARM64 架构上的所有已知问题、症状和解决方案,方便快速定位。
F.1 信号类型速查
| 信号 | 名称 | 常见原因 | 解决方案 |
|---|---|---|---|
| Signal 6 | SIGABRT | C++ 异常被禁用,abort() 被调用 | 编译时加 -fexceptions |
| Signal 7 | SIGBUS | 内存未对齐访问 | 已于 PR #2479 修复 (2023-05),更新代码 |
| Signal 11 | SIGSEGV | 内存访问违规/空指针 | 更新代码,检查 PS 流格式,GDB 调试 |
F.2 Issue 汇总表
| Issue | 硬件 | 信号 | 根本原因 | 解决方案 | 状态 |
|---|---|---|---|---|---|
| #3466 | 多种 ARM | SIGSEGV | PS 流解析异常 + 内存问题 | 更新代码 + 自动重启 | 已关闭 |
| #3202 | RK3588 | SIGABRT | 编译器关闭异常处理 | -fexceptions |
已解决 |
| #2728 | 多种 ARM | - | 内存碎片 + MEM_DEBUG 性能问题 | tcmalloc/jemalloc | 已规避 |
| #2043 | RK3568 | SIGSEGV | 可能网卡驱动 bug | 更新代码 | 已关闭 |
| #4037 | aarch64 | system_error | 端口占用/系统限制 | GDB 调试排查 | 已关闭 |
F.3 编译参数速查
必须添加:
cmake .. -DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC"
推荐添加:
cmake .. -DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC -faligned-new" \
-DENABLE_TCMALLOC=ON
调试编译:
cmake .. -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC" \
-DENABLE_ASAN=ON
F.4 运行时问题速查
| 现象 | 排查命令 | 可能原因 | 解决方案 |
|---|---|---|---|
| 容器频繁重启 | docker logs zlmediakit |
Signal 11 崩溃 | 更新镜像/源码编译 |
| 内存只增不减 | cat /proc/$(pidof MediaServer)/status |
内存碎片 | 使用 tcmalloc |
| 流播放卡顿 | top, iostat |
CPU/IO 瓶颈 | 关闭转码,限制并发 |
| GB28181 无法注册 | netstat -ulnp | grep 15060 |
端口未监听 | 检查防火墙,重启容器 |
| WebRTC 无法播放 | netstat -ulnp | grep 8000 |
UDP 端口被阻 | 检查防火墙规则 |
F.5 Docker vs 源码编译选择建议
| 场景 | 推荐方式 | 理由 |
|---|---|---|
| 快速验证/测试 | Docker | 简单快捷,自动重启可缓解崩溃 |
| 生产环境(关键业务) | 源码编译 | 可针对具体 CPU 优化,稳定性更好 |
| 频繁崩溃 | 源码编译 | 可添加 -fexceptions 等必要参数 |
| 资源受限 | Docker | 无需编译环境,节省磁盘空间 |
F.6 官方 ARM64 修复时间线
| 时间 | 修复内容 |
|---|---|
| 2023-05 | PR #2479: 修复 ARM 内存对齐 SIGBUS 问题 |
| 2023-08 | PR #2800: 修复 close_stream 与 getMediaList 并发崩溃 |
| 2024-12 | @xia-chu 表示考虑添加 ARM64 CI 自动编译 |
| 2025-12 | PR #4582: 修复 RtspSession/RtspPusher 空指针崩溃 |
| 2026-04 | 尚未实现 ARM64 CI 自动编译和二进制发布 |
F.7 社区已知兼容硬件
| 芯片 | 型号 | 系统 | 状态 | 备注 |
|---|---|---|---|---|
| 瑞芯微 | RK3568 | 多种 Linux | ✅ 基本稳定 | 更新代码后正常 |
| 瑞芯微 | RK3588 | Ubuntu 20.04 | ⚠️ 需注意 | 需加 -fexceptions |
| 飞腾 | S5000C | 统信UOS20 | ⚠️ 待验证 | 本手册目标平台 |
| 鲲鹏 | 920 | Ubuntu 20.04 | ✅ 正常 | 社区反馈良好 |
| 树莓派 | 4B | Raspberry Pi OS | ⚠️ 偶发崩溃 | 建议源码编译 |
文档结束 如有问题,请参考各项目的官方文档或 GitHub Issues。 文档版本: v1.0 最后更新: 2026-04-29