ラズベリーパイにカメラを接続し、スマホやパソコンで動画が見れるようにした際に3つの手段をクライアントからの使いやすさ、サーバー(ラズパイ側の)準備の手軽さ、映像の低遅延で比較した結果を整理します。
環境
・ラズベリーパイ Pi 3 (固定IP:192.168.100.90とします)
・クライアントPC Mac
試した内容
1.RTSPストリーミング
2.GstreamerによるHTTPストリーミング
3.mjpeg-streamer
1.RTSPストリーミング
RTSPとは
「Real Time Streaming Protocol」という名前のプロトコルで、「映像・音声のリアルタイムなストリーミング配信を制御」を目的としています。
ネットワークカメラでよく使われる方法のようです。
1-1. 動画配信側(ラズパイ)の設定
カメラ動作は確認済みとします。
/etc/modulesの末尾にbcm2835-v4l2を追記します。
1 2 3 4 5 6 7 8 9 |
$ sudo nano /etc/modules # /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. i2c-dev bcm2835-v4l2 |
v4l2rtspserverをインストール
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// モジュールのインストール $ sudo apt-get install cmake $ sudo apt-get install subversion $ sudo apt-get install liblivemedia-dev // homeに移動 $ cd ~ // コンパイル&インストール $ git clone https://github.com/mpromonet/h264_v4l2_rtspserver.git $ cd h264_v4l2_rtspserver $ sudo cmake . $ sudo make install |
ラズパイからのRTSPで動画を配信します。
1 |
$ sudo v4l2rtspserver |
1-2. クライアント側の設定
VLCプレイヤーを使用します。
ファイル>ネットワークを開く
ラズパイのIPアドレスが「192.168.100.90」の場合、
rtsp://192.168.100.90:8554/unicast
と設定します。
成功すると動画を見ることができます。
体感としては1~2秒の遅延といった所でした。
手軽ですが、VLCプレイヤーから毎回動かすのが面倒というデメリットがあります。
2.GstreamerによるHTTPストリーミング
Webアプリで埋め込んで使うにはRTSPは敷居が高そうだったのでHTTPで配信する方法(HLS)も試してみました。
HLSとは
HTTP Live StreamingというAppleが実装したHTTPベースのメディアストリーミングプロトコルのこと。
m3u8という形式のセグメントファイルの場所、再生時間、再生順序などを記述したメタデータファイルとtsという形式のセグメントファイル(細切れの動画ファイル)から構成されます。
2-1. 動画配信側(ラズパイ)の設定
GStreamerをインストールします。
1 2 |
sudo apt install autoconf automake libtool $ sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev |
GStereamerで作ったストリーミング動画を配信するためのサーバーを用意します。
nodeのインストールを確認します。
1 2 |
$ node -v v10.15.2 |
動画配信の置き場を作成します。
1 2 3 4 5 6 |
mkdir nodejs $ cd nodejs $ npm init $ npm install --save express $ touch app.js $ mkdir wwwroot |
app.jsの内容は以下とします。
1 2 3 4 5 6 7 8 9 |
var express = require('express'); var app = express(); app.use(express.static('wwwroot')); var port = 3000; app.listen(port,function(){ console.log("サーバがポート%dで起動しました。モード:%s",port,app.settings.env) }); |
サーバーを起動します。
1 2 |
$ node app.js サーバがポート3000で起動しました。モード:development |
サーバーから動画配信するための video.jsファイルを下記の構成で設置します。
使用するファイルは下記のgithubからダウンロードします。
https://github.com/zgw426/GStreamerSample/tree/master/sample01
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
pi@raspberrypi:~/nodejs/wwwroot $ tree . ├── output.m3u8 ├── segment00220.ts ├── segment00221.ts ├── segment00222.ts ├── segment00223.ts ├── segment00224.ts ├── segment00225.ts ├── segment00226.ts ├── segment00227.ts ├── segment13714.ts ├── segment13715.ts ├── segment13716.ts ├── segment13717.ts ├── segment13718.ts ├── segment13719.ts ├── segment13720.ts ├── segment13721.ts ├── static │ ├── css │ │ └── video-js.min.css │ └── js │ ├── video.min.js │ ├── videojs-contrib-hls.min.js │ └── videojs-contrib-media-sources.min.js ├── streamtest.html |
streamtest.htmlの中身はラズパイのIPアドレスに応じて変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Video.js Sample</title> <link href="static/css/video-js.min.css" rel="stylesheet"> <script src="static/js/video.min.js"></script> <script src="static/js/videojs-contrib-media-sources.min.js"></script> <script src="static/js/videojs-contrib-hls.min.js"></script> </head> <body> <video id="test" class="video-js vjs-default-skin vjs-big-play-centered" contro$ width="640" height="480" data-setup="{}"> <source src="http://192.168.100.90:3000/output.m3u8" type="application/x-mpeg$ </video> <script> var player = videojs('test'); player.play(); </script> </body> </html> |
最後にGStreamerを動作させます。
1 2 3 4 5 6 7 |
pi@raspberrypi:~/nodejs/wwwroot $ sudo gst-launch-1.0 -v -e v4l2src device=/dev/video0 \ > ! video/x-h264,width=640,height=480,framerate=15/1 \ > ! h264parse ! mpegtsmux \ > ! hlssink max-files=8 target-duration=5 \ > location=./segment%05d.ts \ > playlist-location=output.m3u8 \ > playlist-root=./ |
2-2. クライアント側の設定
ブラウザから
http://192.168.100.90:3001/streamtest.html
と打ち込むと、動画が閲覧できます。
ブラウザから見れるのでWebアプリへの埋め込みはvideoタグで一発でできて容易そうですが、私の環境では10秒以上の遅延がありました。
DURATIONの設定等で遅延を減らせるかもしれませんが、一旦ここまで。
3.mjpeg-streamer
3-1. 動画配信側(ラズパイ)の設定
mjpeg-streamerをインストールします。
1 2 3 4 |
$ sudo apt-get install -y cmake libv4l-dev libjpeg-dev imagemagick $ git clone https://github.com/jacksonliam/mjpg-streamer.git $ cd mjpg-streamer/mjpg-streamer-experimental $ make |
mjpeg-streamerを起動します
1 |
$ ./mjpg_streamer -o "./output_http.so -p 8090 -w ./www" -i "./input_raspicam.so -x 640 -y 480 -fps 30 -q 10" |
3-2. クライアント側の設定
ブラウザから
http://192.168.100.90:8090
にアクセスするとロゴ入りのページに飛びます。
映像だけ見たい場合には
http://192.168.100.90:8090/javascript_simple.html
からアクセスします。
クライアントPCのWebアプリからの使用を想定して下記のHTMLで動作確認しても問題なく動作しました。
1 2 3 4 5 6 7 8 9 10 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>mjpeg-streamer Sample</title> </head> <body> <img src="http://192.168.100.90:8090/?action=stream"> </body> </html> |
遅延が1~2秒と少なく、セットアップが簡単でした。
結論
ラズベリーパイのカメラで動画をWebブラウザから見たい場合には、
mjpeg-streamerがセットアップが簡単で遅延も少なかったです。
項目 | RTSP | Gstreamer(HLS) | mjpeg-streamer |
クライアントからの使いやすさ | △ | ◯ | ◯ |
サーバー(ラズパイ)の準備の手軽さ | ◯ | △ | ◯ |
映像の低遅延 | ◯ | × | ◯ |
追記
気付いたらmjpeg-streamerが落ちてる時があったので、cronで監視して落ちてたら起動させます。
~/mjpg-streamer/mjpg-streamer-experimental 配下に
mjpg_check.sh
mjpg_reboot.sh
というシェルスクリプトを作成し以下を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/Users/mac #!/usr/bin/sh while true do isAlive=`ps -ef | grep mjpg_streamer | grep -v grep | wc -l` if [ $isAlive = 1 ]; then echo "mjpg_streamer on process" sleep 30s else echo "reboot mjpg_streamer" cd ~/mjpg-streamer/mjpg-streamer-experimental sh ./mjpg_reboot.sh fi sleep 30s done |
1 |
./mjpg_streamer -o "./output_http.so -p 8090 -w ./www" -i "./input_raspicam.so -x 640 -y 480 -fps 30 -q 10" |
cronで1分毎にmjpg_check.shを動作させます。
1 2 |
$crontab -e * * * * * /bin/sh ~/mjpg-streamer/mjpg-streamer-experimental/mjpg_check.sh |
cron自体が起動しているかは以下で確認。
1 2 3 4 |
$ /etc/init.d/cron status ● cron.service - Regular background program processing daemon Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2020-11-02 14:33:21 JST; 4h 50min ago |
Active: active (running)となっていれば起動しています。もし起動していなかったら $ /etc/init.d/cron start で起動させます。
参考にしたサイト
・RTSP
https://qiita.com/zono_0/items/43fc89876977738de402
・GStreamer
https://qiita.com/suo-takefumi/items/aba3db7d639a8b1a8981
・mjpeg-streamer