#経緯
とある顔識別エンジンに、入力映像をRTSPで送信するために、RapberryPiで仕組みを実装した話。
RapberryPiで、RTSPで配信するのはv4l2rtspserverでできる。
が、送信しながらRapberryPiに繋げたモニタ上に表示するにはどうすればいいだろう?
VLCは、遅延が大きすぎて使うには不便だ。
ChromiumのKioskモードで表示させたい。
ブラウザでRTSP受信して表示できたっけ?
と、いう訳でWebRTCの手番。
#失敗
v4l2rtspserverで、/dev/video0 のデータを送信している間、WebRTCで/dev/video0にアクセスはできません。
#改善
v4l2rtspserverの製作者である Michel Promenet氏のとこに答えがあった。
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
$ docker pull mpromonet/v4l2rtspserver
docker-composeで書きます
---
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
docker pull mpromonet/webrtc-streamer
これもdocker-composeで書きます。
---
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に、対応したページに入れ替えることにする。
中身はこんな感じ。
これで全画面に映像が表示される
<!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には、設定が書いてあるのだが、こんな感じ
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モードで起動させるには、次の様にリクエストする
chromium-browser --kiosk [ページのURL] --display=:0
ホストのIPアドレスを渡して起動させるために、次にようなシェルを組む
#!/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は殆ど表示に遅延なし。
うほい。