ラズパイ+魚眼レンズ+KinesisVideoStreamで低コストの防犯カメラ

# 前置き/要件
- 子供が出入りするコワーキングスペースを運営するにあたり、安全のため店内に防犯カメラを設置したい。
- 店番がいなくなる時間帯が発生するため、撮影データはローカルではなく、クラウド保存にしたい。
- ケーブルを這わせるのが面倒なので、有線LANではなく無線LANで。
- なるべく低コストで。

# 参考記事
- 基本はこちら。ありがとうございます。  
https://qiita.com/mksamba/items/86bdd70e7d289073cdc4  
ぶっちゃけ、私の記事には、gstreamerの設定とコストくらいしか、追加情報ありません。

# 使用機材&サービス
- raspberryPi3 Model B+   
品薄で2019/10/21現在手に入らず。2台設置するので、1台はraspberryPi3 Model Bで構築  
最終的にどちらがどちらだっけ？　という状況になるくらい、CPU負荷やメモリ負荷は変わりませんでした。  
ハードウェアエンコーダ万歳。
- VR 220 Camera  
純正カメラだと画角が狭すぎる。死角をなるべく作らないために魚眼を選択。[製品ページ](https://products.entaniya.co.jp/ja/products/raspberry-pi/)
- KinesisVideoStream
今回のシステムのキモ。冷静に考えると怖ろしいサービス。 ディストピア構築には必須だよなぁ。

# 画質

|cam1|cam2|
|:---:|:---:|
|![p1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60757/15a2c6e1-1e4e-c8dc-38b8-c5b6ab7c2954.jpeg)|![p2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60757/6e4c2dd2-1204-09f4-f0a5-404f1f0aa4d6.jpeg)|

ちょっと広角が効きすぎている気もするが、良しとする。

# ラズパイ設定

- OSはRaspbian Buster Lite（2019-09-26）
せっかくなのでBusterで構築してみる。ライブラリの追加はあるものの、それほど苦労せず。SDカードの負荷を下げる設定をしたくらい。

- 以下、参考程度のインストールスクリプト。
※kinesis用ライブラリの作成で何度かエラーが出て、その都度パッケージを追加している。そのため、このままでは正常に終了しない可能性もあります。ご容赦。

```shell:install.sh
sudo apt-get update
sudo apt-get -y install git
sudo apt-get -y install autoconf cmake bison automake libtool gcc flex
sudo apt-get -y install gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-tools
sudo apt-get -y install gstreamer1.0-omx

sudo apt-get -y install gstreamer1.0
sudo apt-get -y install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base-apps

sudo apt-get -y install libssl-dev libcurl4-openssl-dev liblog4cplus-1.1-9 liblog4cplus-dev glib libglib libglib2.0 libglib2.0-dev

sudo echo 'bcm2835-v4l2' >> /etc/modules

git clone https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp

cd ./amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build
./min-install-script

mkdir -p ~/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib/gstreamer-1.0/
cp -p /home/pi/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/libgstkvssink.so /home/pi/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib/gstreamer-1.0/
```

# gstreamerの設定
- コストとの兼ね合いで、どの設定がよいか色々と試す。
- 以下、カメラ起動用スクリプト

```shell:gstreamer.sh
export GST_PLUGIN_PATH=/home/pi/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib:$GST_PLUGIN_PATH
export LD_LIBRARY_PATH=/home/pi/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib

gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! \
     videoflip method=rotate-180  ! clockoverlay ! \
     video/x-raw,format=I420,width=1440,height=1440,framerate=7/1 ! \
     omxh264enc control-rate=2 target-bitrate=1024000 inline-header=false periodicty-idr=14 ! \
     h264parse ! \
     video/x-h264,stream-format=avc,alignment=au,profile=baseline ! \
     kvssink stream-name="{stream-name}" access-key="{access-key}" secret-key="{secret-key}" aws-region="{aws-region}"

```
サイズは1440x1440。当初は1920x1920で出来ないかトライしたが、raspberryPiのエンコーダ的に不可の模様。
framerateは秒間7コマ。ターゲットビットレートは1M。ただ、実際にkinesis video streamにアップされるビットレートは400k〜500k。画質もそれほど良くなく、カクカクではあるが、監視カメラの用途であれば十分。kinesisVideoStreamの料金はアップするデータ容量で決まるので、今回は低ビットレートが正義。
periodicty-idrはframerateに合わせて設定する必要あり。秒間コマ数*2くらいの値が適当と思われる。
推測が入るが、送信するデータのタイムスタンプと、kinesisVideoStream側のタイムスタンプが10秒以上乖離していると、動画を受け入れてくれない。よって、送信データはなるべくタイムスタンプが近くなるよう、細切れにして送ったほうが良い。ただし、こま切れすぎてもラズパイやネットワークに負荷がかかる。伸るか反るか。有線LANであれば、この限りではないかも。
カメラの向きの関係から、180°のローテートをかけている。
タイムコードの書き出しもしている。

# kinesisVideoStream

特別なことはせず。
1440x1440という、レアなサイズでも問題なく食べてくれる。
データの保存期間は1週間に設定。

# コスト
- 機材費は1台につき1.7万円ほど
- awsへの払いは、月額予測では1台で＄1.6。マジか･･･。
データ保存期間を多少いじったところでそれほど価格変動はないのではないか。aws有能すぎる。

# 問題点

kinesis video streamは長時間運用していると、明らかにブロックノイズが増加する。gstreamer.shの再起動で一旦は解消されるので、1日に1度、再起動するようにしている。原因究明は後日。

追記
深夜、店内が真っ暗な状態で再起動をかけると、暗闇に最適なホワイトバランスで撮影を再開してしまうため、開店後店内の照明をつけるとホワイト過多になり、防犯カメラの用をなさなくなる。仕方なく、1台につき、30分毎にスクリプトを再起動している。2台体制なので、撮影されない時間帯は発生しないが、少々格好悪い。 

<img width="772" alt="screen.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60757/e2017944-bbd2-1803-38a0-a0f7fb604061.png">


ここまでで、最低限の機能は実装。この後は、監視カメラの生存確認のため、lambdaをいじることにする。
ちょっと長くなったので、別記事に。


# 今後の予定
- 動体検知。gstremerを分岐させ、opencvに渡し、動体検知した時間帯を記録しておく。
- その日のダイジェスト動画の作成。動体検知した時間をもとに、kinesisVideoStreamから動画を断片的に取得。全部まとめて1本の動画にした上で保存。5分ほどの動画にするのを目標に。
- ホワイトバランス問題の解決。