档案录像系统需要实现视频采集、编码、存储、检索和播放的完整闭环。我们采用Nginx-RTMP模块作为流媒体服务器,FFmpeg进行视频处理,MySQL存储元数据,前端使用Video.js播放器。
操作系统:Ubuntu 20.04 LTS
最低配置:4核CPU/8GB内存/500GB硬盘(每路摄像头每小时约需1GB存储)
网络要求:每路1080P视频需要4Mbps上行带宽
执行以下命令编译安装带RTMP模块的Nginx:
``` sudo apt update sudo apt install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev wget https://nginx.org/download/nginx-1.20.2.tar.gz wget https://github.com/arut/nginx-rtmp-module/archive/refs/tags/v1.2.2.tar.gz tar -zxvf nginx-1.20.2.tar.gz tar -zxvf v1.2.2.tar.gz cd nginx-1.20.2 ./configure --add-module=../nginx-rtmp-module-1.2.2 --with-http_ssl_module make sudo make install ```编辑配置文件 /usr/local/nginx/conf/nginx.conf:
``` rtmp { server { listen 1935; chunk_size 4096; application live { live on; record all; record_path /var/video/archive; record_unique on; record_suffix -%Y%m%d-%H%M%S.flv; 自动转码为HLS格式 exec ffmpeg -i rtmp://localhost/live/$name -c:a aac -b:a 128k -c:v libx264 -b:v 2500k -f flv -g 60 -r 30 -s 1280x720 -preset superfast -tune zerolatency rtmp://localhost/hls/$name_720p 2>>/var/log/ffmpeg-$name.log; } application hls { live on; hls on; hls_path /var/video/hls; hls_fragment 3s; hls_playlist_length 60s; } } } ```启动Nginx服务:
``` sudo /usr/local/nginx/sbin/nginx ```对于支持RTSP的摄像头,在摄像头管理界面设置:
创建推流脚本 /opt/scripts/push_stream.sh:
``` !/bin/bash CAMERA_IP="192.168.1.100" CAMERA_USER="admin" CAMERA_PASS="password" STREAM_NAME="camera01" ffmpeg -rtsp_transport tcp \ -i "rtsp://${CAMERA_USER}:${CAMERA_PASS}@${CAMERA_IP}:554/Streaming/Channels/101" \ -c copy \ -f flv \ "rtmp://localhost/live/${STREAM_NAME}" ```设置脚本权限并启动:
``` chmod +x /opt/scripts/push_stream.sh nohup /opt/scripts/push_stream.sh > /var/log/camera01.log 2>&1 & ```执行SQL创建数据库结构:
``` CREATE DATABASE video_archive; USE video_archive; CREATE TABLE cameras ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, ip_address VARCHAR(15) NOT NULL, location VARCHAR(200), stream_name VARCHAR(50) UNIQUE, status ENUM('active', 'inactive') DEFAULT 'active', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE video_records ( id INT AUTO_INCREMENT PRIMARY KEY, camera_id INT NOT NULL, file_path VARCHAR(500) NOT NULL, start_time DATETIME NOT NULL, end_time DATETIME NOT NULL, duration INT NOT NULL, file_size BIGINT NOT NULL, resolution VARCHAR(20), FOREIGN KEY (camera_id) REFERENCES cameras(id), INDEX idx_time (start_time, end_time), INDEX idx_camera (camera_id) ); ```创建Python脚本自动记录视频文件信息:
``` import os import pymysql from datetime import datetime import subprocess def get_video_info(file_path): cmd = f"ffprobe -v error -show_entries format=duration,size -of default=noprint_wrappers=1 {file_path}" result = subprocess.run(cmd, shell=True, capture_output=True, text=True) info = {} for line in result.stdout.strip().split('\n'): if '=' in line: key, value = line.split('=') info[key] = value return info def scan_video_files(archive_path): conn = pymysql.connect(host='localhost', user='root', password='your_password', database='video_archive') for root, dirs, files in os.walk(archive_path): for file in files: if file.endswith('.flv'): file_path = os.path.join(root, file) 从文件名解析时间信息 格式:streamname-20231201-143000.flv filename = os.path.splitext(file)[0] parts = filename.split('-') if len(parts) >= 3: stream_name = parts[0] date_str = parts[1] time_str = parts[2] start_time = datetime.strptime( f"{date_str} {time_str}", "%Y%m%d %H%M%S" ) video_info = get_video_info(file_path) duration = int(float(video_info.get('duration', 0))) file_size = int(video_info.get('size', 0)) 插入数据库 with conn.cursor() as cursor: sql = """INSERT INTO video_records (camera_id, file_path, start_time, end_time, duration, file_size) SELECT c.id, %s, %s, DATE_ADD(%s, INTERVAL %s SECOND), %s, %s FROM cameras c WHERE c.stream_name = %s""" cursor.execute(sql, (file_path, start_time, start_time, duration, duration, file_size, stream_name)) conn.commit() conn.close() if __name__ == "__main__": scan_video_files("/var/video/archive") ```设置定时任务每小时执行一次:
``` crontab -e 添加以下行 0 /usr/bin/python3 /opt/scripts/scan_videos.py ```安装PHP和必要扩展:
``` sudo apt install php-fpm php-mysql ```创建配置文件 /usr/local/nginx/conf/vhost.conf:
``` server { listen 80; server_name archive.yourdomain.com; root /var/www/archive; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } HLS视频流访问 location /hls { types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } alias /var/video/hls; add_header Cache-Control no-cache; } 录像文件访问 location /archive { alias /var/video/archive; add_header Content-disposition "attachment"; } } ```
创建 index.php:
``` prepare($query); if ($camera_id) { $stmt->bind_param("sssi", $date, $start_time, $end_time, $camera_id); } else { $stmt->bind_param("sss", $date, $start_time, $end_time); } $stmt->execute(); $result = $stmt->get_result(); ?> ```创建播放器页面 player.php:
``` ```创建自动清理脚本 /opt/scripts/cleanup_old_videos.sh:
``` !/bin/bash RETENTION_DAYS=30 ARCHIVE_PATH="/var/video/archive" 删除超过保留天数的文件 find $ARCHIVE_PATH -name ".flv" -mtime +$RETENTION_DAYS -delete 更新数据库记录 mysql -u root -p'your_password' video_archive -e " DELETE FROM video_records WHERE end_time < DATE_SUB(NOW(), INTERVAL $RETENTION_DAYS DAY)" ```安装并配置Prometheus监控:
``` wget https://github.com/prometheus/prometheus/releases/download/v2.37.0/prometheus-2.37.0.linux-amd64.tar.gz tar -xvf prometheus-2.37.0.linux-amd64.tar.gz cd prometheus-2.37.0.linux-amd64 ```创建监控配置 prometheus.yml:
``` global: scrape_interval: 15s scrape_configs: - job_name: 'nginx_rtmp' static_configs: - targets: ['localhost:80'] - job_name: 'system' static_configs: - targets: ['localhost:9100'] ```/opt/scripts/health_check.sh:
``` !/bin/bash 检查Nginx服务 if ! systemctl is-active --quiet nginx; then systemctl restart nginx fi 检查磁盘空间 DISK_USAGE=$(df /var/video | awk 'NR==2 {print $5}' | sed 's/%//') if [ $DISK_USAGE -gt 90 ]; then 触发紧急清理 /opt/scripts/cleanup_old_videos.sh fi 检查推流进程 if ! pgrep -f "ffmpeg.rtsp" > /dev/null; then 重启所有摄像头推流 pkill -f push_stream.sh /opt/scripts/push_stream.sh fi ```问题1:无法连接RTMP服务器
检查防火墙:sudo ufw allow 1935/tcp
检查Nginx日志:tail -f /usr/local/nginx/logs/error.log
问题2:视频播放卡顿
调整HLS分片大小:修改nginx.conf中的hls_fragment为5s
降低视频码率:将FFmpeg转码参数中的-b:v调整为1500k
问题3:录像文件不完整
检查磁盘空间:df -h /var/video
增加录像缓冲区:在RTMP配置中添加record_max_size 100M