#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
import cv2
import logzero
import datetime
from threading import Thread
from multiprocessing import Process
import numpy
'''
定义目录结构:
|Base_dir
|__Video 存放最终录制视频
|__Temp 存放采集未较正视频
|__Script 存放此脚本
|__log.log日志文件
'''
# 定义常量和基本目录
DIRECTORY = 'Video'
TEMP_DIRECTORY = 'Temp'
# 磁盘占用容量最大限制
SPACE_LIMIT = 80
BASE_DIR = os.path.dirname(os.getcwd())
VIDEO_DIR = os.path.join(BASE_DIR, DIRECTORY)
TEMP_DIR = os.path.join(BASE_DIR, TEMP_DIRECTORY)
# 定义录制视频长度,单位秒
TIME_LENGTH = 180
# 初始日志文件
logzero.logfile(os.path.join(BASE_DIR, 'log.log'), maxBytes=5e6, backupCount=3)
# 多线程采集视频,定义类
class Recorder(Thread):
def __init__(self, name, cap, v_width, v_height, group=None):
super().__init__(group=group, name=name)
self.cap = cap
self.width = v_width
self.height = v_height
self.frame = numpy.zeros((self.width, self.height, 3), dtype=numpy.uint8)
def run(self):
while True:
_, self.frame = self.cap.read()
def get_frame(self):
return self.frame
# 给视频加时间戳
def time_frame(frame):
datet = str(datetime.datetime.now())[:19]
frame = cv2.putText(frame, datet, (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2, cv2.LINE_AA)
return frame
# 计算磁盘占用率
def disk_per(directory):
info = os.statvfs(directory)
free_size = info.f_bsize * info.f_bavail
total_size = info.f_bsize * info.f_blocks
per = round(free_size / total_size * 100)
per = 100 - per
return per
def file_name(video_dir, file_time):
file_n = file_time.strftime('%Y-%m-%d_%H-%M-%S') + '.avi'
video_name = os.path.join(video_dir, file_n)
return video_name
def file_lists(video_dir):
file_lists = []
for path, _, files in os.walk(video_dir):
for file_t in files:
if file_t.endswith('avi'):
file_name = os.path.join(path, file_t)
file_lists.append(file_name)
file_lists.sort(key=lambda x: os.path.getctime(x))
return file_lists
# 较正帧率
def change_fps(temp_file, video_dir, time_length, fourcc, width, height):
temp_cap = cv2.VideoCapture(temp_file)
total_fps = temp_cap.get(7)
fps = round(total_fps / time_length)
video_name = os.path.join(video_dir, temp_file.split(r'/')[-1])
out_file = cv2.VideoWriter(video_name, fourcc, fps, (width, height))
i = total_fps
while i:
ret, frame = temp_cap.read()
if ret:
out_file.write(frame)
i -= 1
logzero.logger.info('{}转换结束'.format(str(video_name)))
out_file.release()
temp_cap.release()
os.remove(temp_file)
def result_video(base_dir, video_dir, temp_dir, space_limit, time_length, fourcc, width, height):
while True:
# print("空间占用率")
# print(disk_per(base_dir))
if disk_per(base_dir) < space_limit:
files_temp = file_lists(temp_dir)
if len(files_temp) > 1:
change_fps(files_temp[0], video_dir, time_length, fourcc, width, height)
else:
files = file_lists(video_dir)
if len(files) > 0:
logzero.logger.info('磁盘空间不足,{}已删除'.format(str(files[0])))
os.remove(files[0])
else:
logzero.logger.info('磁盘空间不足,程序终止,需确认是否有其他文件占用')
break
if __name__ == "__main__":
cap = cv2.VideoCapture(0)
cap_width = int(cap.get(3))
cap_height = int(cap.get(4))
cap_fps = cap.get(5)
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
file_time = datetime.datetime.now()
temp_file = file_name(TEMP_DIR, file_time)
out_video = cv2.VideoWriter(temp_file, fourcc, cap_fps, (cap_width, cap_height))
# 单独创建进程较正视频
Process_Result = Process(target=result_video, name="process_result", args=(
BASE_DIR, VIDEO_DIR, TEMP_DIR, SPACE_LIMIT, TIME_LENGTH, fourcc, cap_width, cap_height,))
Process_Result.daemon = True
Process_Result.start()
# 单独创建线程采集视频
Thread_rec = Recorder("Process-Rec", cap, cap_width, cap_height)
Thread_rec.daemon = True
Thread_rec.start()
while Process_Result.is_alive():
if (datetime.datetime.now() - file_time).seconds >= TIME_LENGTH:
logzero.logger.info('{}录制结束'.format(str(temp_file).split(r'/')[-1]))
out_video.release()
file_time = datetime.datetime.now()
temp_file = file_name(TEMP_DIR, file_time)
out_video = cv2.VideoWriter(temp_file, fourcc, cap_fps, (cap_width, cap_height))
else:
out_video.write(time_frame(Thread_rec.get_frame()))
# if Process_Result.is_alive()==False:
# break
cap.release()
树莓派利用Python制作的一个简单视频监控设备,但是录制的视频不是快了就是慢了,有没有人知道怎么解决一下。个人爱好,小学水平业余折腾爱好者,见笑。
于 2022-04-02 23:41:54 首次发布
该博客介绍了一个实时视频录制系统,使用多线程和多进程进行视频采集和处理。系统监测磁盘空间,当空间不足时删除最旧的视频文件。视频帧率根据预设长度进行调整,并在帧上添加时间戳。程序使用OpenCV库进行视频操作,并通过日志文件记录状态。
摘要由CSDN通过智能技术生成