6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Colaboratoryでscikit-videoを使って動画の読み書きをする

Last updated at Posted at 2019-11-21

scikit-videoを使うと、手軽に動画ファイルの読み込み・書き込みを行うことができる。内部的にはFFmpegが利用されていることもあり、自由度も高い。

scikit-videoのインストール

!pip install scikit-video

Google colaboratory上でscikit-videoを利用するには、pipで手動でライブラリをインストールする必要がある。

Requirement already satisfied: scipy in /usr/local/lib/python3.6/dist-packages (from scikit-video) (1.3.2)
Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from scikit-video) (1.17.4)
Requirement already satisfied: pillow in /usr/local/lib/python3.6/dist-packages (from scikit-video) (4.3.0)
Requirement already satisfied: olefile in /usr/local/lib/python3.6/dist-packages (from pillow->scikit-video) (0.46)
Installing collected packages: scikit-video
Successfully installed scikit-video-1.1.11

2019年11月現在の最新版、1.1.11がインストールされた。

Google Driveのマウント(オプション)

gdrive_path = "/content/gdrive" # マウント先のパス

from google.colab import drive
drive.mount(gdrive_path)

ファイルの読み書きを実験するに当たって、動作確認の手軽さから今回はGoogle Driveを使う。/content/gdriveにGoogle Driveがマウントされるようにする。

動画ファイルの読み込み

参考: Reading and Writing Videos

skvideo.ioモジュールを使うと、動画の読み書きをできる。内部的にはFFmpeg/LibAVが使われている。

一括でメモリーに読み込む

import skvideo.io
import os

path = os.path.join(gdrive_path, "My Drive", "sample.mp4") # マイドライブにあるsample.mp4を読み込む
videodata = skvideo.io.vread(path)

# 最初のフレームを取得する
first_frame = videodata[0]

vreadメソッドを使うと、動画ファイル全体を一度にメモリー上に読み込むことができる。読み込まれたデータは(フレーム数, 縦px, 横px, チャンネル数)の構造をもつndarrayになっている。手軽である反面、容量の大きい動画ファイルの場合は大量のメモリーを使用することになってしまうので、基本的には後述のvreaderを使い1フレームずつ読み込む方法を使った方が良さそうだ。

1フレームずつ読み込む

import skvideo.io
import os

path = os.path.join(gdrive_path, "My Drive", "sample.mp4") # マイドライブにあるsample.mp4を読み込む
videogen = skvideo.io.vreader(path)
for frame in videogen:
  # display_image(frame)...

vreaderを使った読み込みでは、動画ファイルを1フレームずつ読み込んでいくことができる。公式サイトの説明によると、こちらの方法の方がactually faster than loading a video as 1 ndarrayとのことなので、理由がなければvreaderを使う。

videogen = skvideo.io.vreader(path, outputdict={"-r": "3"})

inputdictoutputdictという引数を使うと、FFmpegに対してパラメータを与えることができる。上の例は3FPSで読み込む場合。

動画のメタ情報の取得

metadata = skvideo.io.ffprobe(path)
num_frames = metadata["video"]["@nb_frames"] # マトリョーシカになっている動画ではN/A

skvideo.io.ffprobeを使うと、FFmpegのツールであるffprobeを使った動画のメタ情報の取得ができる。

動画ファイルの書き込み

一括で書き込む

import skvideo.io
import os

path = os.path.join(gdrive_path, "My Drive", "skvideo_out.mp4") # マイドライブにskvideo_out.mp4というファイルを出力する
skvideo.io.vwrite(path, videodata) # videodataは映像の全フレームを(フレーム数, 縦px, 横px, チャンネル数)のndarray形式で指定

読み込み同様、メモリ上のデータを一括でファイルに出力する方法も用意されているが、基本的には1フレームずつ処理して書き込んでいった方がパフォーマンスが良さそうだ。

1フレームずつ書き込む

import skvideo.io
import os

path = os.path.join(gdrive_path, "My Drive", "skvideo_out.mp4") # マイドライブにskvideo_out.mp4というファイルを出力する
writer = skvideo.io.FFmpegWriter(path)

# 1フレームずつ書き込む
writer.writeFrame(frame1)
writer.writeFrame(frame2)
writer.writeFrame(frame3)
...

writer.close()

FFmpegWriterを使うと、1フレームずつ映像を書き込んでいくことができる。FFmpegWriterはその名の通りFFmpegを使って動画の出力を行うので、フレームレートなど出力のためのFFmpeg用のパラメータをそのまま渡して適用することができる。例えば、FPS=1で出力したいような場合は下記のように指定できる。

writer = skvideo.io.FFmpegWriter(path, inputdict={"-r": "1"}, outputdict={"-r": "1"})

サンプル

以下のコードは、元動画から1フレームずつ画像を読み込み、10フレーム毎に間引いて10倍速にして出力する。

!pip install scikit-video


import os
import skvideo.io
import skvideo.datasets
from tqdm import tqdm
from google.colab import drive

gdrive_path = "/content/gdrive" # マウント先のパス
drive.mount(gdrive_path)

src_path = os.path.join(gdrive_path, "My Drive", "source.mp4") # 元となるファイルはマイドライブのsource.mp4
out_path = os.path.join(gdrive_path, "My Drive", "skvideo_10x.mp4") # マイドライブにskvideo_10x.mp4というファイルを出力する

writer = skvideo.io.FFmpegWriter(out_path, inputdict={"-r": "1"}, outputdict={"-r": "1"})

videogen = skvideo.io.vreader(src_path)
for i, frame in enumerate(tqdm(videogen)):
  if i % 10 == 0:
    writer.writeFrame(frame)
writer.close()
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?