タイトルの通り、スクリーンキャプチャ動画収録機能を実装します。今回はスタートとストップを任意のタイミングで実行したかったのでthreading.Event()
を用いています。単純にwhileでループさせればもっと簡易的にスクリーンキャプチャを撮ることができると思います。
仕組み 🔗
仕組みはシンプルです。pyautoguiでスクリーンショットを連続で撮り、その画像をcv2でくっつける、というものです。 スクリーンショットはcv2でもできるので、わざわざpyautoguiを使わなくても良いかもしれません。
コード 🔗
screen_capture.py
import numpy as np
import cv2
import pyautogui
import os
import time
import threading
import shutil
# ループ処理用デコレータ
def setInterval(interval):
def decorator(function):
def wrapper(*args, **kwargs):
stopped = threading.Event()
def loop(): # executed in another thread
while not stopped.wait(interval): # until stopped
function(*args, **kwargs)
t = threading.Thread(target=loop)
t.daemon = True # stop if the program exits
t.start()
return stopped
return wrapper
return decorator
class ScreenCapture:
NAME = 'screen_capture'
IMAGE_EXTENSION = 'jpg'
VIDEO_EXTENSION = 'mp4'
def __init__(
self,
path: str = '.',
fps: int = 10,
):
self.img_cv_list = []
self.path = path
self.fps = fps
self.dir_name = '{}_{}'.format(self.NAME, time.strftime('%Y%m%d%H%M%S'))
self.dir_path = '{}/{}'.format(self.path, self.dir_name)
self.__stop_flag = None
def start(self):
self.__print_log('started')
os.makedirs(self.dir_path, exist_ok=True)
self.__stop_flag = self.__screenshot() # @setInterval の戻り値を self で状態管理
def stop(self):
self.__stop_flag.set() # set() で @setInterval が止まる
self.__print_log('stopped')
def save(self):
img_height, img_width, _ = np.asarray(pyautogui.screenshot()).shape
video_filename = '{}/{}_{:010d}.{}'.format(self.dir_path, self.dir_name, 1, self.VIDEO_EXTENSION)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
video = cv2.VideoWriter(video_filename, fourcc, self.fps, (img_width, img_height))
for i, img_cv in enumerate(self.img_cv_list):
img_filename = '{}/{}_{:010d}.{}'.format(self.dir_path, self.dir_name, i+1, self.IMAGE_EXTENSION)
cv2.imwrite(img_filename, img_cv)
video.write(img_cv)
video.release()
self.__print_log('saved')
def clear(self):
shutil.rmtree(self.path)
self.__print_log('cleared')
def __print_log(self, message):
print('{} {}.'.format(self.NAME, message))
@setInterval(0.1)
def __screenshot(self):
img = pyautogui.screenshot()
img_array = np.asarray(img)
img_cv = cv2.cvtColor(img_array, cv2.COLOR_BGR2RGB)
self.img_cv_list.append(img_cv)
使い方 🔗
main.py
from screen_capture import ScreenCapture
screen_capture = ScreenCapture()
# キャプチャのスタート
screen_capture.start()
# キャプチャのストップ
screen_capture.stop()
# キャプチャ動画の保存
screen_capture.save()
# キャプチャをクリア
screen_capture.clear()
以上ありがとうございました。