143 lines
5.3 KiB
Python
143 lines
5.3 KiB
Python
import cv2
|
|
import time
|
|
from datetime import datetime
|
|
import os
|
|
import paramiko
|
|
from config import SFTP_CONFIG, RTSP_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 = [] # 记录待上传的视频文件
|
|
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
base_output_dir = os.path.join(script_dir, "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() |