因捡回来的摄像头不支持直连NAS,但支持rtsp,所以自己用python写了一个录像功能
1.需要自己改代码中的smb和rtsp的连接配置
2.需要设备支持rtsp协议,笔者部署了一个支持rtsp的海康威视摄像头。需要一个支持SMB的机器存放文件
3.程序运行会产生大量本地硬盘读写,待优化
version >= python3.9
requirements.txt:
anyio==3.7.1
certifi==2023.7.22
cffi==1.15.1
colorama==0.4.6
cryptography==41.0.3
exceptiongroup==1.1.3
h11==0.14.0
httpcore==0.17.3
httpx==0.24.1
idna==3.4
numpy==1.25.2
opencv-python==4.8.0.76
pyasn1==0.5.0
pycparser==2.21
pysmb==1.2.9.1
pyspnego==0.9.1
sniffio==1.3.0
tqdm==4.66.1
record.py
import cv2
import logging
from datetime import datetime
import ctypes
import os
import platform
from smb.SMBConnection import SMBConnection
from concurrent.futures import ProcessPoolExecutor
import time
def smb_connect(user_name, passwd, ip, port):
'''
建立smb服务连接
:param user_name:
:param passwd:
:param ip:
:param port: 445或者139
:return:
'''
samba = None
status = False
try:
samba = SMBConnection(user_name, passwd, '', '', use_ntlm_v2=True)
samba.connect(ip, port)
status = samba.auth_result
except:
samba.close()
return samba, status
def video_record(formatted_time,record_second):
# 海康威视rtsp的url,需要修改user:password@ip:port
cap = cv2.VideoCapture("rtsp://user:password@ip:port/Streaming/Channels/101")
frame_s = cap.get(5)
# 打印帧率
# print("the frame is:" + str(frame_s))
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
ret, frame = cap.read()
time_frame = frame_s * record_second
num = 0
while ret:
if num == 0:
filename = str(formatted_time) + ".mp4"
video_writer = cv2.VideoWriter(filename, fourcc, frame_s, size, True)
ret, frame = cap.read()
img = cv2.resize(frame, (640, 360), interpolation=cv2.INTER_LINEAR)
video_writer.write(frame)
num = num + 1
if num == time_frame:
video_writer.release()
# 上传视频到 SMB 目录
with open(filename, 'rb') as video_file:
# 打开一个smb连接
# smb 需要填写登录账户密码,ip,端口默认445
samba, status = smb_connect('user', 'password', '192.168.50.87', 445)
service_name = "monitor"
smb_dir = 'MonitorSave'
samba.storeFile(service_name, os.path.join(smb_dir, filename), video_file)
samba.close()
num = 0
os.remove(filename) # 删除本地视频文件
break
#samba.storeFile(service_name, os.path.join(smb_dir, filename), frame)
video_writer.release()
cv2.destroyAllWindows()
cap.release()
def get_free_space_mb(folder):
if platform.system() == 'Windows':
free_bytes = ctypes.c_ulonglong(0)
ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(folder), None, None, ctypes.pointer(free_bytes))
return free_bytes.value / 1024 / 1024 / 1024
else:
st = os.statvfs(folder)
return st.f_bavail * st.f_frsize / 1024 / 1024
if __name__ == '__main__':
# 当前目录
file_path = os.path.abspath('.')
# 获取目录的剩余空间,单位mb
storage_space = get_free_space_mb(file_path)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
pool = ProcessPoolExecutor(max_workers=10)
while(storage_space>=50):
try:
# 获取当前时间
current_time = datetime.now()
# 格式化时间为 "年月日时分" 格式
formatted_time = current_time.strftime("%Y%m%d%H%M%S")
logging.info("recording: "+str(formatted_time)+".mp4")
# 单个视频文件持续记录时间,单位秒
record_time = 60
#video_record(formatted_time,record_time)
pool.submit(video_record,formatted_time,record_time)
# 错位1s,防止录像缺漏
time.sleep(record_time-1)
except(Exception) as e:
logging.error(str(e))