【初心者】Amazon Kinesis Video Streams を使ってみる（ラズパイカメラからの送信）

# 目的
- 動画配信について勉強する必要があり、とりあえず基本を実機で試してみることにした。

# Kinesis Video Streams とは（自分の理解）
- カメラからの動画を受信してストリームとして保存し、配信や解析を行う他のサービスに渡すことができるサービス。

# やったこと
- ラズパイ(Raspberry Pi 3 model B) にUSBカメラ(Buffalo BSWHD06M) を接続する。
- ラズパイにKinesis Video Streams のProducerSDKをインストール、設定する。
- ラズパイからの動画をAWS東京リージョンに送信し、マネージメントコンソールの動画プレビュー画面で確認する。

# 構成図

![kvs02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/f50aae7c-1a22-dfcf-fa1b-9f7ce60b75b2.png)

# 作業手順
[公式ドキュメント：Kinesis ビデオストリーム の使用開始](https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/getting-started.html)に従い作業を行う。

## AccessKeyの発行
- IAMユーザを作成し、「AmazonKinesisVideoStreamsFullAccess」権限を付与し、AccessKeyを発行する。後でラズパイ側での動画送信コマンドの実行時に使用する。

## ストリームの作成
- マネージメントコンソールのKinesis Video Streamsの画面で、ストリーム「mksamba-video-stream」を作成する。ストリームとは、動画をカメラ等（producer）から受信し、蓄積し、別サービス等（consumer）に渡すためのパイプのような領域。

## ラズパイの準備
- OS(Raspbian Stretch) をインストールする。環境としては以下の通り。

```
pi@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.8 (stretch)
Release:        9.8
Codename:       stretch
```

- USBカメラが/dev/video0として認識されていることを確認する。

## クライアントのインストール
- [公式ドキュメント：ステップ 3: Kinesis ビデオストリームにデータを送信する](https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/gs-send-data.html)に従い、ラズパイ用のクライアント（C++プロデューサーライブラリ）を入れる。
- ドキュメント通りに、「Raspbianの場合は…」というところを見ながらコマンドを入力したが、エラーが出まくるので、エラーから推測してパッケージを追加する。

```
$ git clone https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp 
$ sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-tools
$ sudo apt-get install gstreamer1.0-omx
(kinesis-video-native-build ディレクトリに移動し、) $ ./min-install-script
```

- 以下は公式ドキュメントにはないが追加インストールしたもの。まず ./min-install-script 実行時に cmakeがないと言われるので、cmakeを追加。

```
$ sudo apt-get install cmake
```

- 次に「Could NOT find Log4cplus (missing:  LOG4CPLUS_LIBRARIES LOG4CPLUS_INCLUDE_DIR)」等のエラーが出るので、以下を追加。
- 以下のパッケージが必要なことについて、公式ドキュメントには載っていなかったが、[githubのREADME](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp/blob/master/install-instructions-linux.md)には記載があった。

```
$ sudo apt-get install libssl-dev libcurl4-openssl-dev liblog4cplus-1.1-9 liblog4cplus-dev
```

- 公式ドキュメントに記載の以下のコマンドでカメラ動画のKinesis Video Streamsへの送出を試みたが、いくつかエラーが発生。順次修正する。

```
$ gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,format=I420,width=640,height=480 ! omxh264enc control-rate=2 target-bitrate=512000 periodicity-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name="MyKinesisVideoStream" access-key="YourAccessKey" secret-key="YourSecretKey" aws-region="YourAWSRegion"
```

- まず、「WARNING: erroneous pipeline: プロパティ "periodicity-idr" がエレメント "omxh264enc-omxh264enc0" にありません」というWARNING(実際にはエラーであり動画送信不可）が発生。ここは「periodicity-idr」を「periodicty-idr」に修正する。（英単語としては「periodicity」だが、パラメータとしては「periodicty」で実装されている様子。）
- 次に、「WARNING: erroneous pipeline: エレメント "kvssink" がありません」というWARNINGが発生。公式ドキュメントには記載がないため、AWSサポートにも確認し、以下の設定を追加。kvssinkの実体であるlibgstkvssink.soをgstreamerから参照できるようパスを調整する必要がある。

```
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
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/

```

# 動画送信の確認

![kvs01a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/79882b72-24e3-e6cf-84e5-00018ad2d3aa.png)

- 無事カメラの入力がKinesis Video Streamsに送信され、マネージメントコンソールで表示可能になった。
- 右下に「ライブ -8.0秒」と表示されており、筆者の環境だと、動画がアップロードされ、表示されるまでに約8秒かかっている。どこの区間に時間がかかっているかは不明（ラズパイのエンコード処理、インターネット経由のアップロード、AWS側での処理等）。
- ラズパイ側の仕組みのざっくり理解としては以下の通り。
    - gstreamerというのは、ストリーミングメディアアプリケーションを作成するためのフレームワーク。
    - kvssink というのは、AWSがgstreamer用に開発したプラグイン（シンクエレメント）。エレメントというのは、gstreamerの中で入出力を行うパイプのようなもので、シンクエレメントは、外部出力を行うエレメント。


# 所感
- クライアントのインストールに結構時間がかかってしまった。linuxの知識等があればドキュメントに記載がなくてももう少し脳内補完できるのかも、、
- 次のステップとしてはRekognition Video等との連携を実施してみたい。

# 参考記事
- [GStreamer アプリケーション開発マニュアル](http://oss.infoscience.co.jp/gstreamer/index.html)