目的
メイン処理とWebカメラ映像表示処理を分けられないかと思った。
また、任意のタイミングで録画の開始/停止を行いたかった。
環境
・Ubuntu 22.04
・Python 3.10.12
・Webカメラ Logicool C270
ポイント
・threading
カメラ映像取得ループ処理をスレッドにしている
・RecStart,RecStop
変数recordingのTrue/Falseが録画開始/停止のトリガーになる
・Lock
VideoWriter.release()の後にVideoWriter.write()が起きないようにする。
Lockすることで処理の順番が write() => release() になる。
ソースコード
main.py
#!/usr/bin/python3
import time
import Camera as cm
if __name__ == "__main__":
cam = cm.Camera()
while True:
time.sleep(10)
cam.RecStart("test")
time.sleep(10)
cam.RecStop()
Camera.py
import threading
import datetime
import os
import cv2
class Camera:
def __init__(self):
index = 0
devpath = "/dev/" + "video" + str(index)
self.Setting(devpath, index, 1280, 720, 30)
self.thread = threading.Thread(target=self.Open, daemon=True)
self.thread.start()
def Setting(self, devpath, index, W, H, FPS):
self.devpath = devpath
self.index = index
self.W = W
self.H = H
self.FPS = FPS
self.cap = cv2.VideoCapture(self.index)
self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','P','G'))
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.W)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.H)
self.cap.set(cv2.CAP_PROP_FPS, self.FPS)
self.vwr = cv2.VideoWriter()
self.vwr_Lock = threading.Lock()
self.thread = threading.Thread()
self.recording = False
self.filename = ""
def Open(self):
while True:
ret, frame = self.cap.read()
if ret:
cv2.imshow('Capture', frame)
if self.recording:
self.vwr_Lock.acquire()
if self.vwr.isOpened():
self.vwr.write(frame)
self.vwr_Lock.release()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
self.Close()
def Close(self):
if self.vwr.isOpened():
self.vwr.release()
if self.cap.isOpened():
self.cap.release()
cv2.destroyAllWindows()
def RecStart(self, filename):
self.recording = True
self.filename = filename
self.vwr.release()
self.vwr = cv2.VideoWriter(f'{self.filename}.mp4', cv2.VideoWriter.fourcc('m','p','4','v'), self.FPS, (self.W, self.H))
def RecStop(self):
self.recording = False
if self.vwr.isOpened():
self.vwr_Lock.acquire()
self.vwr.release()
self.vwr_Lock.release()
rename = f'{self.filename}' + '_' + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + '.mp4'
os.rename(f'{self.filename}.mp4', f'{rename}')