一、前置软硬件准备
1.1 硬件配置要求(适配100㎡以内小型档案室,4路摄像头)
• 服务器:x86架构,CPU≥i5 10代,内存≥16G,系统盘≥256G固态,录像盘容量按单路1080P每天占20G计算,需满足至少180天留存要求,挂载路径固定为/data/record,权限设为777
• 摄像头:支持GB/T 28181协议的1080P红外枪机,无需特定品牌,只要支持RTMP推流即可
• 配套设备:8口PoE交换机1台,超五类网线若干
1.2 软件资源准备
• 操作系统:CentOS 7.9 Minimal,下载地址:http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
• 启动盘烧录工具:Rufus 4.4,下载地址:https://github.com/pbatard/rufus/releases/download/v4.4/rufus-4.4.exe
• 依赖组件:ZLMediakit流媒体服务、MySQL 5.7、FFmpeg、Python3
二、服务端基础环境部署
2.1 操作系统初始化配置
烧录启动盘后插入服务器,选择U盘启动完成系统安装,分区时单独划分3.5T以上分区挂载到/data/record,进入系统后执行以下命令关闭防火墙和SELinux,避免端口拦截:
```
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
```
接着安装基础依赖包:
```
yum install -y wget git gcc gcc-c++ cmake mysql-devel ffmpeg python36 python36-pip
```
2.2 流媒体服务ZLMediakit部署
拉取源码编译安装:
```
git clone https://gitee.com/xia-chu/ZLMediaKit.git
cd ZLMediaKit
git submodule update --init
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j4
```
修改配置文件ZLMediaKit/release/linux/Debug/config.ini,直接替换对应模块内容:
```
[record]
enableMP4=1
mp4AsHls=0
mp4SavePath=/data/record
mp4MaxSecond=3600
mp4Sample=1
[hook]
enable=1
on_record_complete=http://127.0.0.1:8080/on_record_complete
```
后台启动流媒体服务:
```
cd ../release/linux/Debug
./MediaServer -d &
```
2.3 MySQL数据库安装与配置

执行以下命令安装MySQL 5.7:
```
wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpm -ivh mysql57-community-release-el7-11.noarch.rpm
yum install -y mysql-community-server --nogpgcheck
systemctl start mysqld
systemctl enable mysqld
```
获取初始密码并修改,替换命令中的初始密码为执行grep 'temporary password' /var/log/mysqld.log返回的结果:
```
mysql -uroot -p初始密码
进入MySQL命令行后依次执行
set global validate_password_policy=0;
set global validate_password_length=4;
alter user 'root'@'localhost' identified by '123456';
create database record_index default charset utf8;
use record_index;
CREATE TABLE `records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`camera_id` varchar(32) NOT NULL COMMENT '摄像头编号',
`file_path` varchar(255) NOT NULL COMMENT '录像文件路径',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`file_size` bigint(20) NOT NULL COMMENT '文件大小字节',
PRIMARY KEY (`id`),
KEY `idx_time` (`start_time`,`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
exit;
```
2.4 录像索引服务部署
先安装Python依赖:
```
pip3 install flask pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
```
新建/opt/app.py文件,复制以下完整代码:
```
from flask import Flask, request, jsonify
import pymysql
import os
from datetime import datetime
app = Flask(__name__)
DB_CONFIG = {
"host": "127.0.0.1",
"user": "root",
"password": "123456",
"database": "record_index"
}
录像生成完成回调接口
@app.route('/on_record_complete', methods=['POST'])
def on_record_complete():
data = request.json
camera_id = data.get('app')
file_path = data.get('file_path')
start_time = datetime.fromtimestamp(int(data.get('start_time')))
end_time = datetime.fromtimestamp(int(data.get('end_time')))
file_size = os.path.getsize(file_path)
conn = pymysql.connect(DB_CONFIG)
cursor = conn.cursor()
sql = "INSERT INTO records(camera_id, file_path, start_time, end_time, file_size) VALUES(%s, %s, %s, %s, %s)"
cursor.execute(sql, (camera_id, file_path, start_time, end_time, file_size))
conn.commit()
cursor.close()
conn.close()
return jsonify({"code": 0})
录像查询接口
@app.route('/query_record', methods=['GET'])
def query_record():
camera_id = request.args.get('camera_id')
start_time = request.args.get('start_time')
end_time = request.args.get('end_time')
conn = pymysql.connect(DB_CONFIG)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = "SELECT FROM records WHERE camera_id = %s AND start_time >= %s AND end_time <= %s"
cursor.execute(sql, (camera_id, start_time, end_time))
res = cursor.fetchall()
cursor.close()
conn.close()
return jsonify({"code": 0, "data": res})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=False)
```
配置开机自启,新建/etc/systemd/system/record.service文件:
```
[Unit]
Description=Archive Record System
After=network.target mysqld.service
[Service]
Type=simple
WorkingDirectory=/opt
ExecStart=/usr/bin/python3 /opt/app.py
Restart=always
User=root
[Install]
WantedBy=multi-user.target
```
启动服务并设置开机自启:
```
systemctl daemon-reload
systemctl enable record
systemctl start record
```
三、摄像头对接配置
1. 所有摄像头设置为和服务器同网段静态IP,比如服务器IP为192.168.1.10,摄像头依次设为192.168.1.20~192.168.1.23
2. 登录摄像头后台,开启RTMP推流,推流地址填rtmp://服务器IP/live/摄像头编号,比如第一个摄像头推流地址为rtmp://192.168.1.10/live/cam01,摄像头编号需唯一,后续查询录像时会用到
3. 配置摄像头码率为2Mbps,帧率25帧,确保录像清晰度和存储空间平衡
四、功能校验与常见问题排查
4.1 功能校验
• 实时流校验:浏览器访问http://服务器IP:8080/live/摄像头编号.flv,可正常播放实时画面即配置成功
• 录像校验:等待1小时后,执行命令curl "http://服务器IP:8080/query_record?camera_id=cam01&start_time=2024-01-01 00:00:00&end_time=2024-12-31 23:59:59",返回对应录像文件信息即为正常
• 合规校验:执行df -h查看/data/record分区剩余空间,确认可满足至少180天录像留存要求
4.2 常见问题排查
- 摄像头推流失败:检查服务器1935端口是否被占用,摄像头和服务器网络是否可ping通
- 无录像文件生成:检查
/data/record目录权限是否为777,ZLMediakit配置文件中存储路径是否正确
- 无索引数据:检查MySQL服务是否正常运行,ZLMediakit的hook回调地址是否配置正确