RapberryPi 4Bで、v4l2rtspserverとwebrtc-streamerをする

#経緯
とある顔識別エンジンに、入力映像をRTSPで送信するために、RapberryPiで仕組みを実装した話。  

RapberryPiで、RTSPで配信するのはv4l2rtspserverでできる。
が、送信しながらRapberryPiに繋げたモニタ上に表示するにはどうすればいいだろう？

VLCは、遅延が大きすぎて使うには不便だ。
ChromiumのKioskモードで表示させたい。

ブラウザでRTSP受信して表示できたっけ？
と、いう訳でWebRTCの手番。

#失敗
v4l2rtspserverで、/dev/video0 のデータを送信している間、WebRTCで/dev/video0にアクセスはできません。

#改善
v4l2rtspserverの製作者である [Michel Promenet氏](https://github.com/mpromonet)のとこに答えがあった。
webrtc-streamerなら、rtspをWebRTCに仕組みでブラウザに表示できるようになるらしい、/dev/video0から取得する必要はなくなる。
WebRTCに関しては、実装はこれが初めてで、仕組みについて理解はほとんどありません。

が、先の作者が提供してくれているarmv7用のDocker imageを使用すれば、簡単に目的のことが実現できます。

#作業

全部Docker imageで構築します。

#### 環境
RaspberryPi 4B 8GB
RaspberryPi OS(32-bit) with desktop
version: May 2020
Release date: 2020-05-27
Kernel version: 4.19

#### v4l2rtspserver
[mpromonet/v4l2rtspserver](https://hub.docker.com/r/mpromonet/v4l2rtspserver)

```
$ docker pull mpromonet/v4l2rtspserver
```
docker-composeで書きます

```v4l2rtspserver/docker-compose.yaml
---
version: '3'
services:
  rtsp:
    image: 'mpromonet/v4l2rtspserver:latest'
    container_name: 'v4l2rtspserver'
    ports:
      - '8554:8554'
    command: '-G 720x480x15 -S'
    devices:
      - '/dev/video0'
    tty: true
    privileged: true
```
720x480 15fps で配信
commandに書くと、引数つけて実行される様子

配信URLは、rtsp://ホスト名:8554/unicast でユニキャスト受信できる。
VLCとかで見れます。

#### webrtc-streamer
[mpromonet/webrtc-streamer](https://hub.docker.com/r/mpromonet/webrtc-streamer)

```
docker pull mpromonet/webrtc-streamer
```
これもdocker-composeで書きます。

```webrtc-streamer/docker-compose.yaml
---
version: '3'
services:
  webrtc:
    image: 'mpromonet/webrtc-streamer:latest'
    container_name: 'webrtc-streamer'
    ports:
      - '8000:8000'
    volumes:
      - ./webrtc-streamer/app/html/new.html:/app/html/index.html
      - ./webrtc-streamer/app/html/config.json:/app/html/config.json
    tty: true
    privileged: true
```

http://[ホスト名]:8000
にアクセスすると、

```
WebRTC stream name to connect is missing
Usage :
http://[ホスト名]:8000/?video=<WebRTC video stream name>&audio=<WebRTC audio stream name>&options=<WebRTC options>
```
ってダイアログが表示されると思うので、先ほどのRTSP配信URLをつけてやる

```
http://[ホスト名]:8000/?video=rtsp://[RTSPホスト名]:8554/unicast
```
と、ブラウザに表示されるはずだ

#やりたいこと
RaspberryPiには、3.5inchモニタが接続してある。
ChromiumのKioskモードで全画面に映像を表示したい。
なので、先のdocker-composeで書いた、volumesに、対応したページに入れ替えることにする。

中身はこんな感じ。
これで全画面に映像が表示される

```/app/index.html
<!DOCTYPE html>
<html>
<head>
<script src="libs/request.min.js" ></script>
<script src="libs/adapter.min.js" ></script>
<script src="config.json"></script>
<script src="webrtcstreamer.js"></script>
<script>
var params = new URLSearchParams(location.search);
if (params.has("video")) config.video = params.get("video");
if (params.has("audio")) config.audio = params.get("audio");
if (params.has("options")) config.options = params.get("options");

var webRtcServer = null;
window.onload = () => {
	webRtcServer = new WebRtcStreamer('video', config.server);
	webRtcServer.connect(config.video, config.audio, config.options);
}
window.onbeforeunload = () => {
	webRtcServer.disconnect();
}
</script>
<style>
body { margin: 0; padding: 0; overflow: hidden; background-color: black; }
video { text-align: left; width: 100%; }
</style>
</head>
<body>
	<video id="video" muted playsinline />
</body>
</html>
```

config.jsonには、設定が書いてあるのだが、こんな感じ

```/app/html/config.json
const config = {
	'server': 'http://192.168.11.120:8000',
	'video': 'rtsp://192.168.11.120:8554/unicast',
	'audio': '',
	'options': 'rtptransport=tcp&timeout=60'
};
```

http://[ホスト名]:8000 でアクセスすると、config.jsonの設定内容で表示される。

今回、同じホスト上でRTSPの配信を行っており、また、IPアドレスが変わる場合があるので、クエリで配信ホストのIPアドレスを含んだURLをChromiumに渡して表示させることにする

### Kioskモード

ChromiumをKioskモードで起動させるには、次の様にリクエストする
![Bad Request]()

```
chromium-browser --kiosk [ページのURL] --display=:0
```

ホストのIPアドレスを渡して起動させるために、次にようなシェルを組む

```kiosk.sh
#!/bin/sh
ip=$(ifconfig | grep -A 1 'wlan0' | tail -n 1 | cut -b 14-27)
chromium-browser --noerrdialogs --kiosk http://localhost:8000/index.html?video=rtsp://${ip}:8554/unicast --display=:0
```

これで起動すれば、全画面に表示されるはずだ

#結果

RTSPで送信しながら、モニタにWebRTCで表示させることができましたよ。
RTSPはVLCで表示してるので、遅延があるけど、Chromiumで表示しているWebRTCは殆ど表示に遅延なし。
うほい。

![image](https://drive.google.com/uc?export=view&id=16I0kH0YXGBuBnahdl13pGK-Bs_FD0j6t)