ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法（1/3）

1. [ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法（1/3）](https://qiita.com/nmatsui/items/d1f7ceaa84cf805ee636) <br/> **概要編** <-- 今回
2. [ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法（2/3）](https://qiita.com/nmatsui/items/8bc9dc224fd9d288c56c) <br/> クラウド側環境構築編
3. [ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法（3/3）](https://qiita.com/nmatsui/items/30adbeebd15b4c3de0ea) <br/> ロボット側環境構築編

# はじめに
労働力不足の解消や作業員の負担軽減を目的に、今後業務ロボット・サービスロボットの導入が加速すると言われています。
<img width="593" alt="富士経済グループプレスリリース_18036.png" src="https://qiita-image-store.s3.amazonaws.com/0/37648/a5a8df6e-8abf-70cc-df30-be36b3e2403e.png">
> 出展: 富士経済グループ プレスリリース 第18036号　「業務・サービスロボット関連の世界市場を調査」 2018/04/16
> http://www.group.fuji-keizai.co.jp/press/pdf/180416_18036.pdf

屋外やビルあるいは家庭で多くのサービスロボットが稼働している世界では、それらのロボットのカメラ映像をリアルタイムに分析し遠隔地から視聴できれば、いろいろ役に立ちそうです。例えば屋外で迷子を探したり、勤務先から自宅のペットの様子をみたり。

ただし、それらのカメラをインターネットに直接接続するのは、セキュリティ上のリスクがあります。インターネット側からカメラへ直接到達できるようにネットワークを組んでしまうと、カメラやその制御システムにセキュリティホールがある場合に容易に攻撃されてしまいます。
> IPAの「[ネットワークカメラシステムにおける情報セキュリティ対策要件チェックリスト](https://www.ipa.go.jp/security/jisec/choutatsu/nwcs/checklist_nwc.pdf)」でも、「インターネットからアクセス可能なカメラの場合は、リスクをより軽減するためにVPN網やキャリアが提供しているセキュアな閉域網の利用を推奨する」とされています。

そこで今回は、VPNやWebRTCを活用し、ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法について解説します。この記事では、システムの概要を解説します。

# 最終的なシステム構成

今回のシステムは、[Azure Kubernetes Service (AKS)](https://azure.microsoft.com/ja-jp/services/kubernetes-service/)と[Azure VPN Gateway](https://azure.microsoft.com/ja-jp/services/vpn-gateway/)、及びメディササーバである[Kurento](http://www.kurento.org/)を用います。Azure固有のVPN Gateway機能は使っていますが、同様の構成は[AWS EKS](https://aws.amazon.com/jp/eks/)や[Google GKE](https://cloud.google.com/kubernetes-engine/)でも実現できるはずです。

## ブラウザとKurento間の経路確立
ブラウザとKurento間は、WebRTCで接続します。WebRTCは最近のブラウザがあれば動作しますので、VPNクライアント等を別途インストールする必要はありません。

なおNAT越えに必要となるため、STUN&TURNサーバも自前でK8S上に構築しておきます。またKurentoとブラウザ間をWebRTCで接続する際にSDPを交換する必要があるため、シグナリングサーバも別途K8S上へ構築しておきます。
![fig1.png](https://qiita-image-store.s3.amazonaws.com/0/37648/016fc302-f220-bc41-6f46-425196f5337a.png)

## ロボットのカメラとKurento、Kurentoとブラウザ間で映像配信
うまくSDPが交換できて経路が確立すると、ブラウザとKurentoがWebRTCで接続します。この経路はSRTPで暗号化されるため、安全です。またブラウザ側にもKurentoにも、インターネット側から直接アクセス可能なポートを開ける必要はありません。

一方ロボット側は、WebRTCを用いません。クラウドとロボット側LAN内のRaspberry PiでIKEv2でVPNトンネルを敷設し、Raspberry PiのiptablesがNATする形でKurentoとロボット間を到達可能にします。VPNを用いるためこの経路も安全ですし、ロボット側にインターネット側から直接アクセス可能なポートを開ける必要もありません。
> ロボット側でVPNとNATを用いているのは、WebRTCは基本的にブラウザありきの技術だからです。Kurentoのブラウザ用ライブラリを解析し、libwebrtcを用いてロボットのカメラ専用アプリをC++で書くことも可能だとは思いますが、かなり大変だと思います。

![fig2.png](https://qiita-image-store.s3.amazonaws.com/0/37648/23897b24-8ebe-fb62-a744-2fba6785677a.png)
なお上記の図ではブラウザとKurentoが直結していますが、ブラウザ側LANのルータの構成によっては、TURNサーバが間に入ってSRTPパケットを中継せざるを得ない場合があります。
またプロキシを用いてOutbound側も厳密に制御されている企業内LANなど、ネットワークの状況によってはWebRTCが利用できない場合もあります。ご注意ください。

## 実際に動かしてみた動画

自宅で動かしたロボットのカメラ映像をブラウザから視聴した動画。
[![ROSBot2 camera stream on your browser](http://img.youtube.com/vi/oUhFFsa1pwA/0.jpg)](https://www.youtube.com/watch?v=oUhFFsa1pwA)
（動画がYouTubeで再生されます。）

ディスプレイ上に表示した時計をロボットのカメラで撮り、ブラウザ上でその時計を表示（ブラウザへ配信されている映像は、わずかながら遅延している）。
[![ROSBot2 camera stream on your browser](http://img.youtube.com/vi/4WaE9SuMe_w/0.jpg)](https://www.youtube.com/watch?v=4WaE9SuMe_w)
（動画がYouTubeで再生されます。）

## 映像の圧縮方式
### ロボット側
ロボットのカメラは、Motion JPEGで映像をストリーミングすることとします。Motion JPEGは時間軸方向の圧縮を行わないため、CPUやメモリに制限のあるロボットでも、それほど遅延せずに圧縮できます（ただしデータ量が膨大になるため、利用できるネットワークの帯域に合わせて映像の品質や解像度、フレームレートを制限する必要があります）。

### ブラウザ側
一方ブラウザとKurento間では、ブラウザによって適切な圧縮方式が自動的に選択されます。最近のブラウザですと、H264やVP8、VP9あたりが使われると思います。
ただしKurentoがMotionJPEGを適切なコーデックへ自動的に変換してくれますので、このあたりは気にする必要がありません。Kurento便利！

## リアルタイム映像処理への期待
今回の構成は、一度クラウド上のメディアサーバを経由しているため、メディアサーバ上でリアルタイムに画像処理を行い、ロボットのカメラ映像に付加価値をつけることも可能になります。
例えば人物写真から抽出した特徴点を用いて、ロボットのカメラ映像で迷子をハイライトする、といったこともできるようになると期待できます。

## 可用性と性能への課題
しかし残念ながら、今回ご紹介する構成には大きな問題があります。それはKurentoもSTUN&TURNサーバも、KurentoもPodを一つしか起動していないということです。
WebSocketはステートフルなプロトコルのため、シグナリングサーバを単純にスケールアウトするだけでは上手く動作しません。またKurentoのPodが複数起動している場合、視聴したいロボットが接続しているKurentoへブラウザを接続する必要がありますし、Kuentoがダウンした場合にはロボット側・ブラウザ側の双方が経路を再確立する必要があります。このあたりは、今後の課題ですね。

## ソースコード一式
今回作ったアプリケーションのソースコードや、K8S上に環境を構築するYAMLファイル等はすべてgithubで公開しています。もし興味がありましたら、参照してください。

* Kubernetesの環境構築用YAMLファイル
    * https://github.com/nmatsui/kurento-robot-camera-k8s
* STUN & TURN Server
    * https://github.com/nmatsui/kurento-robot-camera-coturn
    * https://cloud.docker.com/repository/docker/nmatsui/kurento-robot-camera-coturn
* WebRTC動作テスト用アプリケーション
    * https://github.com/nmatsui/kurento-robot-camera-loopback
    * https://cloud.docker.com/repository/docker/nmatsui/kurento-robot-camera-loopback
* ロボットカメラ映像配信アプリケーション
    * https://github.com/nmatsui/kurento-robot-camera-mjpeg2many
    * https://cloud.docker.com/repository/docker/nmatsui/kurento-robot-camera-mjpeg2many

# 次回は
ということで、次回はクラウド側の環境構築をしたいと思います。