树莓派利用Python制作的一个简单视频监控设备,但是录制的视频不是快了就是慢了,有没有人知道怎么解决一下。个人爱好,小学水平业余折腾爱好者,见笑。

该博客介绍了一个实时视频录制系统,使用多线程和多进程进行视频采集和处理。系统监测磁盘空间,当空间不足时删除最旧的视频文件。视频帧率根据预设长度进行调整,并在帧上添加时间戳。程序使用OpenCV库进行视频操作,并通过日志文件记录状态。
摘要由CSDN通过智能技术生成
#!/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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值