0
点赞
收藏
分享

微信扫一扫

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

小猪肥 2022-04-02 阅读 92
#!/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'
# 磁盘占用容量最大限制,最大80%占用
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)
    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):
    temp_cap = cv2.VideoCapture(temp_file)
    fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
    width = int(temp_cap.get(3))
    height = int(temp_cap.get(4))
    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):
    while True:
        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)
        else:
            files = file_lists(video_dir)
            logzero.logger.info('磁盘空间不足,{}已删除'.format(str(files[0])))
            os.remove(files[0])


def run_recorder(TEMP_DIR, BASE_DIR, SPACE_LIMIT, TIME_LENGTH):
    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))
    # 单独创建线程采集视频
    Thread_rec = Recorder("Process-Rec", cap, cap_width, cap_height)
    Thread_rec.daemon = True
    Thread_rec.start()

    while True:
        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()))
    cap.release()


if __name__ == "__main__":
    # 单独创建进程较正视频
    Process_Result = Process(target=result_video, name="process_result",
                             args=(BASE_DIR, VIDEO_DIR, TEMP_DIR, SPACE_LIMIT, TIME_LENGTH,))
    Process_Result.daemon = True
    Process_Result.start()
    run_recorder(TEMP_DIR, BASE_DIR, SPACE_LIMIT, TIME_LENGTH)
举报
0 条评论