[python] OpenCVを用いた動画の時間トリミング

# 初めに
pythonでのOpenCVによる動画の時間トリミングに関して、簡単にまとめた。

# OpenCVとは
インテルが開発・公開したオープンソースのコンピュータビジョン向けライブラリ。 [@wiki](https://ja.wikipedia.org/wiki/OpenCV)

>画像処理・画像解析および機械学習等の機能を持つC/C++、Java、Python、MATLAB用ライブラリ。
プラットフォームとしてmacOSやFreeBSD等全てのPOSIXに準拠したUnix系OS、Linux、Windows、Android、iOS等をサポートしている。

日本語での情報も充実している。

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_tutorials.html

# 動画の取り込み
動画の取り込みに関しては、動画の全情報をメモリに展開するわけにはいかないため、
操作可能なようにオブジェクトを生成して取り扱う。

```python
import cv2
video_path = './test.avi'
video = cv2.VideoCapture(video_path) #videoに関するオブジェクト
```

# 動画内の情報取得
動画内の情報は、インスタンス化したオブジェクトから得られる。

```python
frame_rate = video.get(cv2.CAP_PROP_FPS) # フレームレート
frame_width = video.get(cv2.CAP_PROP_FRAME_WIDTH) # 幅pixel
frame_height = video.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高さpixel
frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT) #総フレーム数
print(frame_rate, frame_width, frame_height, frame_count)
```

# 動画の書き出し
動画の書き出しはコーデックを指定し、その他パラメータを指定し、そこに書き込んでいく。

```python
trim_video_path = './trim_video.avi'
fourcc = cv2.VideoWriter_fourcc(*'MJPG') # コーデック
writer_out = cv2.VideoWriter(trim_video_path , fourcc, frame_rate, (frame_width, frame_height))
```

本記事での書き出し方法は、最も単純にvideoをfarmeごとに実体化し、
既定のフレーム数に対してのみ書き込みが発生するように設定した。

```python
frame_min = 1
frame_max = 10

for frame_num in range(frame_max):
    ret, frame = video.read()
    if ret == True:
        if frame_num >= frame_min:
            writer_out.write(frame)
        else:
            break
```

## コーデックに関して
コーデック（CODEC）とは、COmpression（圧縮）/ DECompression（伸長）を意味する、COder（コーダ）/ DECorder（デコーダ）の略称を語源とした用語。
取り扱われる範囲としては、アナログデータとデジタルデータに変換する際や、音声・映像・テキストといったデータを圧縮・伸長する際の、処理そのものや、機器、ソフトフェア、アルゴリズムを含む。
今回のvideoのコーデックに関しても、取り扱うデータの圧縮方式によって適切にエンコード（符号化）・デコード（複号化）を行う必要がある。

動画のfourcc（データフォーマットを一意に識別するための4バイトの並び）に関しては、主だったものの例を以下に示す。

|コーデック|拡張子|
|---|---|
|MP4S |.mp4|
|MP4V |.mp4|
|MJPG |.avi|
|XVID |.avi|
|H263 |.wmv|
|MP4V |.mov|

上記に関して、自身の使用する予定であったX264（H264）は別途対応が必要であった。
理由は下記サイトを見ると、ライセンス関係の問題のようである。

>本来H.264を使うにはMPEG-LAにライセンス料を支払う必要があります。
しかし、OepnH264という、Ciscoがオープンソースとして公開しているビルドされたライブラリを使う限りにおいては、このライセンス料をCiscoが肩代わりしてくれるという契約があるのです。
OpenCVでOpenH264を必要としているのもこれが理由です。
・・・
あくまでビルド済みのバイナリを使う上では使用料いらないよということであって、オープンソースのコードを自分でビルドする場合はこの契約から外れるそうです（つまりライセンス料払う必要がある）。
[引用記事] https://blog.shikoan.com/opencv-h264/

現時点でX264（H264）を使用する場合は、OpenH264（ビルド済みのライブラリ）を利用する必要がある。
OpenCVのバージョンに一致したOpenH264のライブラリをインストールすることで実行が可能になる。
[OpenH264] https://github.com/cisco/openh264/releases


# まとめ
記事全体を以下にまとめる。
処理後は、メモリ解放のため、明示的にvideoオブジェクトをreleaseする。

```python
import cv2
video_path = './test.avi'
trim_video_path = './trim_video.avi'
frame_min = 1
frame_max = 10

video = cv2.VideoCapture(video_path) #videoに関するオブジェクト
frame_rate = video.get(cv2.CAP_PROP_FPS) # フレームレート
frame_width = video.get(cv2.CAP_PROP_FRAME_WIDTH) # 幅pixel
frame_height = video.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高さpixel

fourcc = cv2.VideoWriter_fourcc(*'MJPG') # コーデック
writer_out = cv2.VideoWriter(trim_video_path , fourcc, frame_rate, (frame_width, frame_height))

for frame_num in range(frame_max):
    ret, frame = video.read()
    if ret == True:
        if frame_num >= frame_min:
            writer_out.write(frame)
        else:
            break

writer_out.release()
video.release()
```

# 最後に
自身の経験をメモとしてまとめた。
コーデックに関しては、解決に半日かかってしまった。
ライセンス等含めて注意していきたい。