Windows10でgstreamerを使ってWebカメラを録画する 

# 前置き
世の中なにかとカメラを使って録画しておきたいということがありますよね。
実験データと時間を合わせて撮りたいときとか、カメラアプリもデータをとるスクリプトもなんて操作が多すぎて失敗することもしばしば。
そこで、データをとるスクリプト内にカメラも録画できるようにCLIで操作できるgstreamerを使って録画をしてみようというのがこの記事です。

# 環境
* Windows10
* GStreamer 1.16.2<br>
[ここ](https://gstreamer.freedesktop.org/download/)でダウンロードしたインストーラを使用しました。
ウェブカメラとカメラを使う場合は"complete"ですべてインストールするか、必要そうなパッケージをインストールしてください。"typical"ではプラグインがなくて動きませんでした。あと、powershellから使えるようにbinフォルダのパスを通しておきましょう。
* Webカメラ<br>
今回使用したカメラはIO-DATAのTS-NA220Wというものでhttpでjpegを吐き出してくれるものでした。
* プログラミング言語<br>
文字列でpowershellのコマンドを実行できるのが前提条件です。`python`だったら`subprocess.Popen("ls". shell=True)`みたいな

# まずは動画を取得してみる
私の使用していたウェブカメラはAPIが用意されており、rtspでmp4,mjpegが、httpでjpegがストリーミングで見ることができました。
以下にそれぞれrtspとhttpで動画を取得するコマンドを載せておきます。<>の部分は適宜自分の環境に書き換えてください。
powershellを起動して実行してみましょう。

```:【rtspでmp4】
gst-launch-1.0.exe rtspsrc location=rtsp://<username>:<password>@<IPaddress>:<port>/<path> ! rtph264depay ! queue ! h264parse ! decodebin ! videoconvert ! autovideosink
```


私の使用していたウェブカメラはrtspでmp4をストリーミングできたのですが、映像が遅く、3秒前の自分が映っていたので使い物になりませんでした。

```:【httpでjpeg】
gst-launch-1.0.exe souphttpsrc location=http://<username>:<password>@<IPaddress>:<port>/<path> ! queue ! jpegdec ! videoconvert ! autovideosink
```

# いよいよ録画
映像を取得できることが確認出来たら、次は録画になりますね。
それに使うコマンドはこちら

```:【httpでjpeg】
gst-launch-1.0 --eos-on-shutdown souphttpsrc location=http://<username>:<password>@<IPaddress>:<port>/<path> ! queue ! capsfilter caps=image/jpeg,width=1280,height=720,framerate=25/1 ! jpegdec ! jpegenc ! avimux ! filesink location=<filepath>.avi
```

録画の終了は`Ctrl+C`でできます。`--eos-on-shutdown`をつけることで`Ctrl+C`を使って終了しても動画ファイルが壊れないようになっています。（ちなみにプロセスをキルしたらデータは保存されませんでした）
`souphttpsrc`も`rtspsrc`もフレームをカウントする機能がないので何フレーム後に終了という設定ができず、これを使っています。
あと、`jpegdec ! jpegenc`は非常に頭悪いですがなしだとうまく動かなかったのでこれにしてあります。

さて、これだけだと自分で`Ctrl+C`を打ってあげないとダメなので、`Ctrl+C`を打ってくれるスクリプトも用意する必要があります。
参考：[PowerShellでSendKeysを使ってみた](https://qiita.com/nimzo6689/items/488467dbe0c4e5645745)

使いやすいようにコピペします。

```powershell:sendkey.ps1
Param( $InputStroke, $InputProcessName, $InputWaitTime )

## ここに「PowerShellでSendKeysを使ってみた」をまるまるコピーしました。

Send-Keys $InputStroke -ProcessName $InputProcessName -Wait $InputWaitTime
```


これで準備は整いました。`sendkey.ps1`と`gstreamer`をpythonとかそういうスクリプト内でpowershellのコマンドを実行するだけです！

# 最終的なスクリプト
以下のスクリプトでは指定したURLからjpegをストリーミングして10秒間録画するスクリプトになります。

```python:capture.py
import subprocess

gstCommand = 'start C:/gstreamer/1.0/x86_64/bin/gst-launch-1.0 --eos-on-shutdown souphttpsrc location=http://<username>:<password>@<IPaddress>:<port>/<path> ! queue ! capsfilter caps=image/jpeg,width=1280,height=720,framerate=25/1 ! jpegdec ! jpegenc ! avimux ! filesink location=<filepath>.avi'

sendKeyPath = '<path>/<to>/sendkey.ps1'
gstEndCommand = 'start powershell ' + sendKeyPath + ' "^C" "gst-launch-1.0" 10000'

subprocess.Popen(gstCommand, shell=True)
subprocess.Popen(gstEndCommand, shell=True)
```

このスクリプトではgstreamerを実行しているウィンドウにフォーカスを移してから`Ctrl+C`を送るので、終了時に画面操作をしているとうまく終了しないことがあります。

# まとめ
いやー、撮れてよかった。

#参考

* [PowerShellでSendKeysを使ってみた](https://qiita.com/nimzo6689/items/488467dbe0c4e5645745)
* [Pythonからコマンドを呼び出す（Windows編）](https://qiita.com/_akisato/items/d97b17064df158f0dea0)
* [souphttpsrc](https://gstreamer.freedesktop.org/documentation/soup/souphttpsrc.html?gi-language=c)
* [rtspsrc](https://gstreamer.freedesktop.org/documentation/rtsp/rtspsrc.html?gi-language=c)
* [gst-launch-1.0(1) — gstreamer1.0-tools — Debian unstable — Debian Manpages](https://manpages.debian.org/unstable/gstreamer1.0-tools/gst-launch-1.0.1.en.html)