機械系エンジニアの備忘録

20代独身社会人。仕事では機械・機構の研究開発を行っているエンジニアが、自分の専門分野ではないpythonを扱って楽しむブログです。

MENU

【python】デスクトップ画面をキャプチャ(録画)する簡易ソフトを作る

Numpy、OpenCV、PyAutoGUIを用いてデスクトップ画面をキャプチャ(録画)するソフトを自作する

f:id:stjun:20200509231852g:plain

自分のブログをキャプチャした様子

 pythonの勉強法とその手順を記事にしました。

※2020年11月29 「3.4 前準備3:スクリーンショットの画像の大きさを取得」を追記しました。具体的にはどんなモニタを使用していても動くようにコードを改良しました。またその他のファイル形式で保存する方法を追記しました。

www.stjun.com

www.stjun.com

 

 

1. はじめに

デスクトップ画面を録画したいと思ったことはありませんか?

私は時々思います。特にブログで自作アプリの動作を紹介する時に画像ではなく動画で説明できれば分かりやすいのになと思うことが多々あります。

しかしフリーの動画キャプチャソフトは時間制限があったりロゴが勝手に入ってしまったりと使い勝手が悪く、あまり乗り気じゃありませんでした。

そこで「それならpythonで作ってしまおう」ということで、今回、本当に簡易ではありますがキャプチャソフトを自作してみましたので、コードと動作を紹介します。

 

2. コード

#スクリーンショットを動画にする
import numpy as np
import cv2
import pyautogui as pag
import os
import time

#保存するファイル名
timestr=time.strftime("%Y%m%d-%H%M%S") 
img_dir_name="./formovie"+timestr

#画像保存用ファイルを作成
os.makedirs(img_dir_name, exist_ok=True)

# 動画用の画像(スクリーンショット)を用意
#画像を格納するリスト
img_list = []
img_No = 0
#動画のフレームレイト
FPS=14
#録画したい時間
movie_time=10
#上記フレームレイトと録画時間を満たす繰り返し数
photo_no=FPS*movie_time

#デスクトップ画面の縦横の大きさを取得
img=pag.screenshot()
img=np.asarray(img)
img_height, img_width, channels =img.shape

#繰り返しスクリーンショットを撮り、ファイルに保存
for i in range(0, photo_no, 1):
    img_No = img_No + 1
    img=pag.screenshot()
    img=np.asarray(img)
    img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
    img_output= '{}/{:010d}.png'.format(img_dir_name, img_No)
    cv2.imwrite(img_output, img)
    img_list.append(img_output)

# 保存された画像を繋げて動画作成
fourcc = cv2.VideoWriter_fourcc('m','p','4', 'v')
video  = cv2.VideoWriter('desktop_capture.mp4', fourcc, FPS, (img_width, img_height))
for s in img_list:
    img = cv2.imread(s)
    video.write(img)

video.release()

上記を実行すると記事冒頭のGIF画像のように、10秒間デスクトップ画面が録画されて.mp4で動画ファイルが作成されます。

 

3. 説明

3.1 必要なライブラリのインストール
import numpy as np
import cv2
import pyautogui as pag
import os
import time

まず必要なライブラリを上の5つになります。

① numpy:画像のデータ(配列)を扱うため

② cv2(OpenCV): 配列&動画作成をするため

③pyautogui:スクリーンショットを撮るため

④os:画像格納用のフォルダを作成するため

⑤time:フォルダ名に使用するため

ここでAnacondaを使っていれば、①numpy、④os、⑤timeは予めインストールされています。一方、②cv2と③pyautoguiは自分でインストールする必要があります。

インストール方法は以下2つの過去記事をご覧ください。

www.stjun.com

www.stjun.com

 

3.2 前準備1:保存先として新しいフォルダ作成&名前
#保存するファイル・フォルダの名前
timestr=time.strftime("%Y%m%d-%H%M%S") 
img_dir_name="./formovie"+timestr

#画像保存用ファイルを作成
os.makedirs(img_dir_name, exist_ok=True)

今回、スクリーンショットを大量に作成し、それを繋げて動画を作成します。

その大量のスクリーンショットを保存するためのフォルダとして、makedirs()を使って新規フォルダを作成します。

またフォルダの名前は「formovie+コードを実行した時間」としています。実行すると次のように新しいフォルダができます。20200508-233410は2020年5月8日-23時34分10秒という意味です。

f:id:stjun:20200509221643p:plain

 

3.3 前準備2:動画作成で使う変数を準備
# 動画用の画像(スクリーンショット)を用意
#画像を格納するリスト
img_list = []
img_No = 0
#動画のフレームレイト
FPS=14
#録画したい時間
movie_time=10
#上記フレームレイトと録画時間を満たす繰り返し数
photo_no=FPS*movie_time

img_listは大量のスクリーンショットの情報を保存するためのリストです。

img_Noは各スクリーンショットの名前に番号を付けるための変数です。以下画像のマーカーのように名前末の番号として使われます。

f:id:stjun:20200509222614p:plain

FPSは動画のフレームレートに使う変数です。FPSとは1秒間に何枚の画像を表示するかで、FPS=14は1秒間に14枚の画像を表示するという意味になります。

movie_timeは動画時間になります。movie_time=10は10秒の動画という意味になります。

photo_noは上記FPSと動画時間を満たすために何枚のスクリーンショットを撮れば良いかの変数になります。

 

3.4 前準備3:スクリーンショットの画像の大きさを取得
#デスクトップ画面の縦横の大きさを取得
img=pag.screenshot()
img=np.asarray(img)
img_height, img_width, channels =img.shape

 事前にスクリーンショットの解像度を.shapeで取得しておきます。

これはスクリーンショットの解像度はモニタの大きさで変わるからです。例えばFullHDのモニタを使ってる人は1980×1080、4kのモニタを使ってる人は3840×2160であり、次の3.5で動画にする際にこのスクリーンショットの解像度が必要になるからです。

 

3.5 動画作成用のスクリーンショットを大量に撮る
#繰り返しスクリーンショットを撮り、ファイルに保存
for i in range(0, photo_no, 1):
    img_No = img_No + 1
    img=pag.screenshot()
    img=np.asarray(img)
    img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
    img_output= '{}/{:010d}.png'.format(img_dir_name, img_No)
    cv2.imwrite(img_output, img)
    img_list.append(img_output)

for文を使ってスクリーンショットの画像を大量に集めます。

img_No=img_No+1は以下のように画像ファイルの名前を連番にするためにfor文で1づつ足しています。

f:id:stjun:20200509223409p:plain

次にscreenshot()でスクリーンショットを撮ります。

このままではopencvで扱えないので、opencvでも扱えるようにasarray()でnumpyの配列に変換します。

この時、配列の順番がPILだとRGBなのに対しOpenCVはBGRなので色が変になります。そこでcvtColor()を使ってRGBからBGRに変換しています。

img_outputは画像ファイルの名前となる変数です。

最後にcv2.imwrite()で画像を保存し、img_listにappendで画像の情報(画像の保存場所)を加えます。

これを終わるまでfor文で何度も繰り返します。すると新しく作った「formovie+コードを実行した時間」の名前のフォルダ内に、大量にスクリーンショットが保存されます。

f:id:stjun:20200509224217p:plain

 

3.6 動画を作成する
# 保存された画像を繋げて動画作成
fourcc = cv2.VideoWriter_fourcc('m','p','4', 'v')
video = cv2.VideoWriter('desktop_capture.mp4', fourcc, FPS, (img_width, img_height))
for s in img_list:
    img = cv2.imread(s)
    video.write(img)

video.release()

まず動画の拡張子をcv2.VideoWriter_fourcc()で決めます。今回はMP4にします。

例えばaviにしたい場合は、('D','I','V', '3') とします。

次に動画となる箱として変数videoをVideoWriter()で作ります。引数は、動画ファイルの名前、動画の拡張子、動画のフレームレイト、動画の解像度です。

※ここで動画の解像度は写真の解像度と一致していないとエラーになるので注意してください。どういうことかというと、私は1920×1080のモニターを使っているのでスクリーンショットの画像の解像度は1920×1080です。なのでVideowriter()でも(1920,1080)としています。

次にfor文を用いて、imread()で保存した画像を再度読み出し、先ほど作った動画となる箱の変数videoに1つ1つ画像を書き込んでいきます。

最後にvideo.release()をしたら次のようにmp4の動画が作成されます。

f:id:stjun:20200509225449p:plain

 

3.7 おまけ:動画のファイル形式

今回、動画のファイル形式はmp4ですが、fourcc = cv2.VideoWriter_fourcc('m','p','4', 'v')の中身を変えることでその他形式でも保存が可能です。

例えば、

①.wmvで保存したい場合は、('W','M','V', '1')

②.aviで保存したい場合は、('M','J','P', 'G')

などです。

 

おすすめ書籍 

PyAutoGUIやOpenCVの使用方法が載っている書籍を紹介します。

この3つは非常に丁寧に書かれているのでお勧めです。

Pythonで始めるOpenCV入門

Pythonで始めるOpenCV入門

 

Pythonで始めるOpenCV入門」と 「PythonGUI自動化しよう」については、Amazonの月額読み放題サービス「Kindle unlimited」に加入していれば読み放題です。

初回30日間は無料、退会も簡単なので試しに読んでみてもよさそうです。

 

4. 最後に

いかがだったでしょうか。

ちょっとした画面キャプチャとして使えるので便利です。

いつかTkinterGUIを作り、より使いやすいアプリにしたいと思います。