enebular AWS IoT agent を使用してラズパイのマルチモニター環境を制御してみた。

## はじめに
ラズパイで TCPSClient (INetSyphon) を用いてマルチモニター環境を構築してみた。
マルチモニターの映像構成や映像配信元 (TCPSyphonServer または TCPSpoutServer) を簡単に切り替えられるようにするため、ラズパイ上の TCPSClient を enebular AWS IoT agent を用いて制御 (コントロール) してみた。

## きっかけ
IoTLT 放送部の活動で <A HREF="https://github.com/Palakis/obs-ndi/releases">OBS-NDI</A> というプラグインを使用してネットワークを介して他の PC の映像を中継して配信することが可能だということが分かった。

- NDI: Network Device Interface<br />
NewTek 社によって開発された複数の映像システムを IP ネットワークを介して双方向にやり取りすることができ、リアルタイムに大量の高品質、低遅延かつ高フレーム精度でエンコードし、ビデオ制作ワークフロー支援プロトコル。SDK が無償で配布されています。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/af7b41de-e54d-bb4c-6df9-621284f65ea7.png" width="75%"> 

NDI SDK を調べていくと異なる VJ ソフトウェア間で映像の共有・連携をする際に Mac では <A HREF="http://syphon.v002.info/">Syphon</A> 、Windows では <A HREF="http://spout.zeal.co/">Spout</A> が使用されることが分かった。また、Syphon、Spout　は共有メモリを介したプロセス間通信で映像を取得するため、<A HREF="https://docs.vidvox.net/freebies_ndi_syphon.html">NDISyphon</A> や <A HREF="http://spout.zeal.co/download-spout-to-ndi/">Spout to NDI</A> のツールを使用してネットワークを介して映像を共有・連携をすることが分かった。例えば、<A HREF="https://vidvox.net/">VDMX5</A> は無償版では設定を保存できない制限があるが、フル機能　(NDI/Syphon)　を使用可能であるが、<A HREF="https://docs.derivative.ca/
">TouchDesigner</A>　は無償版 (Non-Commercial) だと NDI In/Out TOP が使用できないので、Syphon Spout In/Out TOP と NDISyphon や Spout to NDI　のツールを組み合わせると同じことが実現できる。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/d02d2ef5-9f10-5586-ddba-33c1b91605b5.png" width="75%">
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/4f3480cb-4852-9047-2e20-ccb75405f72c.png" width="75%">

調べていく過程で、過去に <A HREF="http://techlife.sg/TCPSyphon/">TCPSyphon</A> 、<A HREF="http://techlife.sg/TCPSpout/">TCPSpout</A> という同じ目的の取り組みが存在することが分かった。こちらは Syphon、Spout を <A HREF="https://github.com/libjpeg-turbo">TurboJPEG</A> に変換してネットワークを介して映像を共有・連携する仕組みである。(TCPSyphon という名前は INetSyphon に改められている)
現在、ツールの配布は終了しているようだが、まだ直接ダウンロードできるので URL を残しておく。
https://mypage.techlife.sg/products/TCPSyphon.zip
https://mypage.techlife.sg/products/TCPSpout.zip

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/6eec559e-b0f1-f395-df42-284607957dd6.png" width="75%">

また、TCPSyphon、TCPSpout　を受信できるライブラリとして <A HREF="https://github.com/z37soft/">SDK</A> が公開されており、ラズパイでも受信できるツール <A HREF="http://techlife.sg/TCPSClient/">TCPSClient</A> も公開されている。TCPSClient はトリミング(部分表示)機能を持っているため、部分表示するラズパイを複数組み合わせることでマルチモニター環境を構築できることが分かった。(<A HREF="https://doktor-andy.de/wordpress/?p=1917">参考</A>)
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/08a3a8e2-1165-9532-a61d-c3766789309b.png" width="75%">

※ NDI SDK は ラズパイ等の ARM ライブラリでは送信は対応しているが、受信は対応していない。(NDI SDK Documentation.pdfより抜粋)
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/172f7d71-2c17-1768-e90f-120d9ed5c112.png">

## 構成
例えば、ラズパイ 4 台で 1 つの映像を表示するマルチモニター環境を構築する場合、各ラズパイ上の TCPSClient は以下の引数を指定して起動する。

```bash
# ① 配信元の画像の左上1/4を表示
$ TCPSClient.bin -s 0,0,0.5,0.5 -d 0,0,1920,1080
# ② 配信元の画像の右上1/4を表示
$ TCPSClient.bin -s 0.5,0,1,0.5 -d 0,0,1920,1080
# ③ 配信元の画像の左下1/4を表示
$ TCPSClient.bin -s 0,0.5,0.5,1 -d 0,0,1920,1080
# ④ 配信元の画像の右下1/4を表示
$ TCPSClient.bin -s 0.5,0.5,1,1 -d 0,0,1920,1080
```

また、映像配信元 (TCPSyphonServer または TCPSpoutServer) を切り替える場合は以下の引数を指定して起動する。

```bash
$ TCPSClient.bin -c [映像配信元のIPアドレス] -p [映像配信元のポート番号]
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/52d91288-9c34-bc02-770f-911865fe9f3c.png">

複数のラズパイ上の TCPSClient を簡単に制御できるようにするため、enebular editor でフローを作成し、enebular AWS IoT agent を使用してフローをデプロイする。

## 手順
### 1. Raspberry Pi を AWS IoT に繋いで enebular と連携
以下のページを参照して enebular AWS IoT agent をインストールする。
https://qiita.com/TakedaHiromasa/items/b6828e4ac434bf99325d

enebular-runtime-agent(公式) のインストールスクリプトを実行して、AWS IoT 上にモノ (管理) と証明書 (安全性) が追加されることを確認する。

```bash
$ ssh -t pi@[ラズパイの IP アドレス] \
"wget -qO- https://raw.githubusercontent.com/enebular/enebular-runtime-agent/master/tools/install/install.sh | sudo -E bash -s -- \
--aws-iot-thing-name=[モノの名前] \
--aws-access-key-id=[AWS Access Key ID] \
--aws-secret-access-key=[AWS Secret Access Key] \
--aws-iot-region=[Region]"
```

[AWS Access Key ID] と [AWS Secret Access Key] は AWS IoT 用 IAM ユーザーを作成した際に取得するアクセスー ID とシークレットアクセスキーを設定する。
下記の例では [モノの名前] は

- enebular-test-01
- enebular-test-02
- enebular-test-03
- enebular-test-04

[Region] は

- ap-northeast-1　(アジアパシフィック(東京))

で作成した。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/fb0f5172-d2bc-c114-ece9-d1bd74a8adb3.png" width="49%"> <img src="https://qiita-image-store.s3.amazonaws.com/0/72479/beaa7761-8c72-c3e2-861c-01e3f1219bc8.png" width="49%">


### 2. TCPSClient for Raspberry Pi をインストール
ラズパイへ SSH でログインして、以下のコマンドを実行する。

```bash
# pi ユーザで実行
$ sudo apt-get install libavahi-compat-libdnssd-dev

# enebular ユーザで実行
# $ sudo su - enebular
$ git clone https://github.com/z37soft/INetSyphon_RaspberryPi_SDK
$ cd INetSyphon_RaspberryPi_SDK/RaspberryPi3_Stretch/
$ chmod +x TCPSClient.bin
$ cp TCPSClient.bin ~/
```

### 3. video グループに enebular ユーザを追加
enebular ユーザで TCPSClient.bin が起動されるため、video グループに enebular ユーザを追加する。

```bash
$ sudo gpasswd -a enebular video
```

### 4. enebular agent を enebular editor と連携
enebular editor からラズパイ上のフローの動作を確認したり、フローを操作する場合、enebular agent を —dev-mode オプション付きで起動する必要がある。
/etc/systemd/system/enebular-agent-enebular.service
を変更して —dev-mode オプションを追加する。
ExecStart=/home/enebular/enebular-runtime-agent/ports/awsiot/bin/enebular-awsiot-agent --enable-syslog --daemon-mode
　↓
ExecStart=/home/enebular/enebular-runtime-agent/ports/awsiot/bin/enebular-awsiot-agent --enable-syslog --daemon-mode <font color=#FF0000>--dev-mode</font>

```bash
# 上記の変更
$ sudo vi /etc/systemd/system/enebular-agent-enebular.service

# 設定を反映
$ sudo systemctl daemon-reload

# プロセスを再起動
$ sudo systemctl restart enebular-agent-enebular

# ログを確認 (省略可)
$ sudo journalctl -ex -u enebular-agent-enebular.service
```

### 5. enebular editor でフローを作成
デスクトップを選択してフローを作成する。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/cfddee00-fe4f-5697-8a1b-5eec2f96eb57.png" width="75%">
ブラウザからアクセスすると TCPSClient が起動・停止するフローを作成する。(括弧内はアクセス先の URL)

 - 全画面表示 (http://[ラズパイの IP アドレス]:1880/on)
 - ①配信元の画像の左上1/4を表示 (http://[ラズパイの IP アドレス]:1880/1)
 - ②配信元の画像の右上1/4を表示 (http://[ラズパイの IP アドレス]:1880/2)
 - ③配信元の画像の左下1/4を表示 (http://[ラズパイの IP アドレス]:1880/3)
 - ④配信元の画像の右下1/4を表示 (http://[ラズパイの IP アドレス]:1880/4)
 - 停止 (http://[ラズパイの IP アドレス]:1880/off)

※ ニーズがあるかどうか分かりませんが、enebular でフローを公開しておきます。(´・ω・`)
　https://enebular.com/discover/flow/47b455f5-f4c1-4ca4-94af-267ae9b61705

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/76caf401-1852-5c50-47cb-20a131ce8f5d.png" width="75%">

### 6. enebular editor でフローをラズパイへデプロイ
デプロイを選択してフローをラズパイへ配信する。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/bcd8ad7a-17f9-74cc-92b8-f79df9948790.png" width="49%"> <img src="https://qiita-image-store.s3.amazonaws.com/0/72479/451b8655-bc11-4350-1921-4e394adb5d71.png" width="49%">
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/ba63dbfc-bd5b-1fb2-0fda-cf26942ca7b1.png" width="49%"> <img src="https://qiita-image-store.s3.amazonaws.com/0/72479/2fb91241-71fa-37b0-dcdd-d9f659f0896b.png" width="49%">


### 7. enebular editor の編集 (リモート) でフローの動作を確認 （省略可)
enebular agent を —dev-mode オプション付きで起動すると enebular editor からフローを編集できる。ラズパイ上の動作を確認したり、フローのデバッグ情報を確認する場合に使用する。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/631fc9d0-287b-e623-7c78-5ab358d7e10d.png" width="75%">

## まとめ
マルチモニター環境を構築する製品に <A HREF="https://www.matrox.com/graphics/en/products/gxm/th2go/digital/">Triplehead2Go</A> や <A HREF="https://www.datapath.co.uk/legacy-products/datapath-x4">Datapath X4</A> がありますが、ラズパイを使用して安価・簡易に構築してみました。また、enebular AWS IoT agent と enebular editor を使用して画面構成を操作できるようにしてみました。
みなさんも 良き enebular AWS IoT ライフを！
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/5808611a-555e-c333-8ec4-923ecb164432.jpeg" width="75%">

(追伸: nrgpio のエラー対処方法)
journalctl コマンドで enebular agent のログを確認すると起動時にエラーが出力されていることが確認される。Node-REDから GPIO ピンを制御する場合に使用される rpi-gpio nodes です。

```bash
$ sudo journalctl -ex -u enebular-agent-enebular.service
・・・
service.node-red: 30 Dec 11:07:05 - [error] /home/enebular/enebular-runtime-agent/node-red/node_modules/@uhuru/enebular-node-red/nodes/core/hardware/nrgpio needs to be executable
service.node-red: 30 Dec 11:07:09 - [warn] ------------------------------------------------------
service.node-red: 30 Dec 11:07:09 - [warn] [node-red/rpi-gpio] Error : nrgpio must to be executable
service.node-red: 30 Dec 11:07:09 - [warn] ------------------------------------------------------
・・・
```

エラーを解消するためには nrgpio ファイルに実行権限を付与し、改行コードを変更する必要がある。Windows(CRLF) → Unix(LF) 

```bash
$ chmod +x /home/enebular/enebular-runtime-agent/node-red/node_modules/@uhuru/enebular-node-red/nodes/core/hardware/nrgpio
$ sed -i.bak 's/'$'\r//' /home/enebular/enebular-runtime-agent/node-red/node_modules/@uhuru/enebular-node-red/nodes/core/hardware/nrgpio
```