Files
zydi-web/app/tools/rtsp2video.py
T
2025-02-13 02:15:58 +00:00

143 lines
5.2 KiB
Python

import cv2
import time
from datetime import datetime
import os
import paramiko
from config import SFTP_CONFIG, RTSP_CONFIG, PATH_CONFIG
class SFTPClient:
def __init__(self):
self.hostname = SFTP_CONFIG['hostname']
self.username = SFTP_CONFIG['username']
self.password = SFTP_CONFIG['password']
self.remote_base_path = SFTP_CONFIG['remote_base_path']
self.sftp = None
self.transport = None
self.connect()
def connect(self):
try:
if self.transport and self.transport.is_active():
return
self.transport = paramiko.Transport((self.hostname, 22))
self.transport.connect(username=self.username, password=self.password)
self.sftp = paramiko.SFTPClient.from_transport(self.transport)
print("成功连接到SFTP服务器")
except Exception as e:
print(f"SFTP连接失败: {str(e)}")
raise
def upload_file(self, local_file_path, camera_name):
try:
if not self.transport or not self.transport.is_active():
self.connect()
remote_camera_dir = f"{self.remote_base_path}/{camera_name}"
try:
self.sftp.stat(remote_camera_dir)
except IOError:
self.sftp.mkdir(remote_camera_dir)
remote_file_path = f"{remote_camera_dir}/{os.path.basename(local_file_path)}"
self.sftp.put(local_file_path, remote_file_path)
print(f"文件上传成功: {remote_file_path}")
except Exception as e:
print(f"上传失败: {str(e)}")
self.connect() # 尝试重新连接
# 在主程序开始时创建SFTP客户端实例
sftp_client = SFTPClient()
def record_rtsp_stream(rtsp_url, camera_name, start_delay=0):
RECORD_DURATION = 10
INTERVAL = 120 # 2分钟的循环
UPLOAD_INTERVAL = 600 # 10分钟上传一次
last_upload_time = time.time()
pending_uploads = [] # 记录待上传的视频文件
# 直接使用配置中的路径
base_output_dir = PATH_CONFIG['recordings']
output_dir = os.path.join(base_output_dir, camera_name)
# 创建必要的文件夹
for dir_path in [base_output_dir, output_dir]:
if not os.path.exists(dir_path):
os.makedirs(dir_path)
time.sleep(start_delay)
while True:
try:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = os.path.join(output_dir, f'{camera_name}_{timestamp}.avi')
# 创建视频捕获对象
cap = cv2.VideoCapture(rtsp_url)
if not cap.isOpened():
raise Exception(f"无法连接到RTSP流: {rtsp_url}")
# 获取原始视频属性并计算缩放后的尺寸
fps = 10
original_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
original_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
scale_factor = 0.7
width = int(original_width * scale_factor)
height = int(original_height * scale_factor)
# 创建视频写入对象
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(output_file, fourcc, fps, (width, height))
print(f"开始录制 {camera_name}: {output_file}")
frame_count = 0
total_frames = fps * RECORD_DURATION
while frame_count < total_frames:
ret, frame = cap.read()
if not ret:
break
resized_frame = cv2.resize(frame, (width, height))
out.write(resized_frame)
frame_count += 1
time.sleep(1/fps)
cap.release()
out.release()
print(f"录制完成 {camera_name}: {output_file}")
pending_uploads.append(output_file) # 添加到待上传列表
# 检查是否需要批量上传
current_time = time.time()
if current_time - last_upload_time >= UPLOAD_INTERVAL:
print(f"开始批量上传 {camera_name} 的视频文件")
# 上传累积的视频文件
for file_path in pending_uploads:
if os.path.exists(file_path): # 确保文件存在
sftp_client.upload_file(file_path, camera_name)
pending_uploads = [] # 清空待上传列表
last_upload_time = current_time
print(f"{camera_name} 的视频文件批量上传完成")
time.sleep(INTERVAL - RECORD_DURATION)
except Exception as e:
print(f"错误 {camera_name}: {e}")
time.sleep(5)
if __name__ == "__main__":
rtsp_url1 = RTSP_CONFIG['A01']['url']
rtsp_url2 = RTSP_CONFIG['B02']['url']
from threading import Thread
# 创建两个线程,使用固定的摄像头名称
t1 = Thread(target=record_rtsp_stream, args=(rtsp_url1, RTSP_CONFIG['A01']['name'], 0))
t2 = Thread(target=record_rtsp_stream, args=(rtsp_url2, RTSP_CONFIG['B02']['name'], 60))
t1.start()
t2.start()
t1.join()
t2.join()