# 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 适配联网环境 | --- ## 目录 ### 一级导航 1. [文档概述](#一文档概述) 2. [环境说明](#二环境说明) 3. [环境初始化](#三环境初始化) 4. [服务部署](#四服务部署) 5. [配置联动](#五配置联动) 6. [验证步骤](#六验证步骤) 7. [常见问题排查](#七常见问题排查) 8. [附录](#八附录) ### 二级导航 **一、文档概述** - [1.1 部署架构](#11-部署架构) - [1.2 部署方式选择](#12-部署方式选择) **二、环境说明** - [2.1 硬件环境](#21-硬件环境) - [2.2 软件环境](#22-软件环境) - [2.3 统信UOS版本确认方法](#23-统信uos版本确认方法) - [2.4 网络环境](#24-网络环境) **三、环境初始化** - [3.1 确认系统版本和包管理器](#31-确认系统版本和包管理器) - [3.2 安装 Docker](#32-安装docker) - [3.3 配置 Docker 国内镜像加速(推荐)](#33-配置-docker-国内镜像加速推荐) - [3.4 安装常用工具](#34-安装常用工具) - [3.5 创建部署目录](#35-创建部署目录) **四、服务部署** - [4.1 拉取 Docker 镜像](#41-拉取-docker-镜像) - [4.2 准备配置文件](#42-准备配置文件) - [4.3 启动服务](#43-启动服务) - [4.4 部署 ZLMediaKit(单独运行方式)](#44-部署-zlmediakit单独运行方式) - [4.5 部署 GoWVP(Owl)(单独运行方式)](#45-部署-gowvpowl单独运行方式) **五、配置联动** - [5.1 ZLMediaKit Hook 配置](#51-zlmediakit-hook-配置) - [5.2 GoWVP 环境变量配置](#52-gowvp-环境变量配置) - [5.3 重启服务使配置生效](#53-重启服务使配置生效) - [5.4 联动验证](#54-联动验证) **六、验证步骤** - [6.1 验证脚本](#61-验证脚本) - [6.2 手动验证步骤](#62-手动验证步骤) - [6.3 推流测试](#63-推流测试) **七、常见问题排查** - [7.1 Docker 无法启动](#71-docker-无法启动) - [7.2 容器启动后立即退出](#72-容器启动后立即退出) - [7.3 ARM64 镜像无法运行](#73-arm64-镜像无法运行) - [7.4 GoWVP 无法连接 ZLMediaKit](#74-gowvp-无法连接-zlmediakit) - [7.5 GB28181 设备无法接入](#75-gb28181-设备无法接入) - [7.6 性能问题](#76-性能问题) - [7.7 ARM64 架构稳定性问题(重要)](#77-arm64-架构稳定性问题重要) **八、附录** - [附录A: 端口清单](#附录a端口清单) - [附录B: 源码编译 ZLMediaKit(备用方案)](#附录b源码编译zlmediakit备用方案) - [附录C: 源码编译 GoWVP(备用方案)](#附录c源码编译gowvp备用方案) - [附录D: 防火墙配置](#附录d防火墙配置) - [附录E: 参考链接](#附录e参考链接) - [附录F: ARM64 架构问题速查表](#附录farm64-架构问题速查表) --- ## 一、文档概述 本手册指导您在**可联网的生产环境**中,于**飞腾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版本确认方法 在**生产环境服务器**上执行以下命令确认系统版本: ```bash # 查看操作系统详细信息 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 确认系统版本和包管理器 ```bash # 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版本 - 龙蜥/欧拉):** ```bash # 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自带仓库安装: > ```bash > # 直接使用系统仓库安装 > sudo yum install -y docker docker-compose > sudo systemctl start docker > sudo systemctl enable docker > ``` **如果系统使用 `apt` (D版本 - Debian):** ```bash # 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 通过静态二进制安装(备用方案) 如果包管理器安装失败,可使用静态二进制: ```bash # 创建临时目录 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 在国内访问不稳定,建议配置镜像加速器: ```bash # 创建/编辑 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 安装常用工具 ```bash # 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 创建部署目录 ```bash # 创建部署根目录 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 镜像 ```bash # 拉取 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" ``` **国内网络加速(如拉取缓慢或失败):** ```bash # 方案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,请务必修改以下两个配置:** ```bash # 获取服务器实际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`: ```bash 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`: ```bash 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=404 Not Found

您访问的资源不存在!


ZLMediaKit-4.0
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 启动服务 ```bash 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 的场景。 ```bash # 单独运行 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 融合部署,此节可跳过。 ```bash # 单独运行 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 的联动已通过以下方式配置完成: 1. **ZLMediaKit Hook 回调**: ZLMediaKit 在流注册、播放、推流等事件发生时,通过 HTTP POST 请求通知 GoWVP 2. **GoWVP RESTful API**: GoWVP 通过 ZLMediaKit 的 HTTP API 控制流的拉取、转码、录制等操作 3. **共享存储**: 两个容器通过 bind mount 共享 `./data/record` 目录,用于录像文件存储 ### 5.1 ZLMediaKit Hook 配置 上述 `zlm-config.ini` 中已包含 Hook 配置: ```ini [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` 中已包含环境变量配置: ```yaml 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 重启服务使配置生效 ```bash cd /opt/owl-zlmediakit docker-compose restart # 等待30秒后检查状态 sleep 30 docker-compose ps ``` ### 5.4 联动验证 ```bash # 查看 ZLMediaKit 日志,确认 Hook 回调成功 docker logs zlmediakit | grep -i "hook" # 查看 GoWVP 日志,确认收到 ZLMediaKit 事件 docker logs gowvp | grep -i "zlm\|hook" ``` --- ## 六、验证步骤 ### 6.1 验证脚本 创建并运行验证脚本: ```bash 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 ```bash # 获取服务器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 ```bash # 测试 GoWVP Web 界面 curl -I "http://${SERVER_IP}:15123" # 在浏览器中访问管理界面 # http://<服务器IP>:15123 # 默认账号密码请查看 GoWVP 官方文档 ``` #### 6.2.3 验证 GB28181 端口 ```bash # 检查 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 的摄像头或推流工具,可以进行测试: ```bash # 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` 失败 **排查步骤**: ```bash # 查看详细错误 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` 看不到运行的容器 **排查步骤**: ```bash # 查看容器退出日志 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 镜像) **解决方案**: ```bash # 检查镜像架构 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 失败 **排查步骤**: ```bash # 检查 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 **排查步骤**: ```bash # 检查 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 性能问题 **现象**: 视频卡顿、延迟高 **优化建议**: ```bash # 查看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](https://github.com/ZLMediaKit/ZLMediaKit/issues/3466) **问题描述**: 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 可能原因分析 1. **内存对齐问题**: ARM64 架构对内存对齐要求更严格,某些数据结构在 x86 上能正常工作但在 ARM 上触发 SIGSEGV 2. **并发访问竞争**: FrameMerger 在多线程环境下可能存在 race condition 3. **Codec 解析异常**: 某些摄像头发送的 PS 流格式不规范,ARM 版解码器处理异常时未正确保护 4. **Docker 环境差异**: Docker 在 ARM64 上的 QEMU 模拟或 seccomp 策略可能影响行为 #### 7.7.5 规避方案与解决方案 **方案一:使用官方最新镜像(推荐尝试)** ```bash # 确保使用最新 master 分支镜像,可能已修复 # 官方维护者持续在修复 ARM64 相关问题 docker pull zlmediakit/zlmediakit:master docker inspect zlmediakit/zlmediakit:master | grep -E "Created|Revision" ``` **方案二:启用容器自动重启** ```yaml # 在 docker-compose.yml 中已配置 restart: always # 崩溃后容器会自动重启,业务中断时间 < 10 秒 services: zlmediakit: restart: always # 可选:增加重启策略 deploy: restart_policy: condition: any delay: 5s max_attempts: 10 ``` **方案三:限制单路流的并发处理** ```ini # 在 config.ini 中降低并发处理线程数 [general] # 减少事件轮询线程数(默认等于 CPU 核心数) # 可尝试设置为物理核心数的一半 # 注意: 此配置需查阅最新文档确认参数名 [ffmpeg] # 关闭转码,减少编解码压力 cmd=%s -re -i %s -c copy -f flv %s ``` **方案四:使用 host 网络模式(已默认配置)** ```yaml # docker-compose.yml 中已配置 network_mode: host # 避免 Docker 桥接网络在 ARM64 上的性能开销和潜在 bug services: zlmediakit: network_mode: host ``` **方案五:监控并自动恢复** ```bash # 创建监控脚本 /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 定时任务 ``` **方案六:源码编译(终极方案)** ```bash # 如果 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](https://github.com/ZLMediaKit/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()` 导致进程终止 **解决方案**: ```cmake # 在 CMakeLists.txt 中添加 if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") endif() ``` **或在 cmake 命令中指定**: ```bash cmake .. -DCMAKE_CXX_FLAGS="-fexceptions" ``` > ⚠️ **重要**: `-fexceptions` 是 GCC 标准选项,不是临时 hack。ZLMediaKit 大量使用 C++ 异常,在 ARM 上编译**必须**显式启用。 --- **Issue #2728 - ARM 内存"泄漏"问题** | 项目 | 详情 | |------|------| | **平台** | ARM (aarch64), Ubuntu 18, 内存 4G | | **现象** | 调用 `getStatisticJson` 接口时系统卡死;开启 `ENABLE_MEM_DEBUG` 后机器完全卡住 | | **本质** | **内存碎片**,非真正泄漏 | **详细分析**: 1. **内存碎片问题**: - ZLMediaKit 调用 `free()` 将内存返还给 glibc 的 ptmalloc - 但 ptmalloc **不会立即将内存返还给操作系统**(出于性能考虑) - 导致 `RSS` 内存居高不下,看起来像泄漏 2. **`ENABLE_MEM_DEBUG` 的陷阱**: ```cmake # 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** 3. **解决方案 - 使用 tcmalloc**: ```cmake # 编译时启用 tcmalloc cmake .. -DENABLE_TCMALLOC=ON ``` - tcmalloc 采用 **per-CPU 缓存** 机制,更好地管理内存碎片 - 在 RTP 断流重连场景下,内存可以稳定复用 **tcmalloc 静态库编译注意事项**: ```bash # 编译 gperftools 时需要加 -fPIC ./configure CFLAGS="-fPIC" CXXFLAGS="-fPIC" make ``` **运行时加载**: ```bash LD_PRELOAD=libtcmalloc.so.4 ./MediaServer ``` 4. **替代方案 - jemalloc**: ```cmake # 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) ``` **可能原因**: 1. **RK 系列网卡驱动 bug**(与 RK3399 类似) > "rk3339 的网卡驱动是有 bug 的!如果是从上面往别处 tcp 发送大的数据包,在 tcp 的 ip 数据报分片以后会出现校验和计算错误" 2. 交叉编译环境配置问题 3. 缺少必要的系统库 **状态**: Issue 已关闭,标题显示"问题已经解决,谢谢",但未详细说明解决方案。 **建议**: 如遇到类似问题,优先尝试: 1. 更新到最新代码 2. 检查网卡驱动版本 3. 在 GDB 下调试获取完整堆栈 --- #### 7.7.9 ARM64 编译优化建议 **必加编译选项**: | 选项 | 用途 | 必要性 | |------|------|--------| | `-fexceptions` | 启用 C++ 异常处理 | **必须** | | `-pthread` | 线程支持 | **必须** | | `-fPIC` | 位置无关代码(动态库需要) | **推荐** | | `-faligned-new` | 对齐内存分配 | **推荐** | **完整编译命令示例**: ```bash 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)**: ```bash # 创建工具链文件 /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" - **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优化,可以选择源码编译: ```bash # 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(备用方案) ```bash # 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 & ``` > 或者使用预编译二进制(联网环境可直接下载): > ```bash > 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: 防火墙配置 ```bash # 如果使用 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 编译参数速查 **必须添加**: ```bash cmake .. -DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC" ``` **推荐添加**: ```bash cmake .. -DCMAKE_CXX_FLAGS="-fexceptions -pthread -fPIC -faligned-new" \ -DENABLE_TCMALLOC=ON ``` **调试编译**: ```bash 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