人気記事

javascript RaspberryPi

Webアプリからラズパイの動画ストリーミングを再生する方法3選

更新日:

ラズベリーパイにカメラを接続し、スマホやパソコンで動画が見れるようにした際に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を追記します。

$ 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をインストール

// モジュールのインストール
$ 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で動画を配信します。

$ 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をインストールします。

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のインストールを確認します。

$ node -v

動画配信の置き場を作成します。

$ mkdir nodejs
$ cd nodejs
$ npm init
$ npm install --save express
$ touch app.js
$ mkdir wwwroot

app.jsの内容は以下とします。

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)
});

サーバーを起動します。

$ node app.js
サーバがポート3000で起動しました。モード:development

サーバーから動画配信するための video.jsファイルを下記の構成で設置します。

使用するファイルは下記のgithubからダウンロードします。

https://github.com/zgw426/GStreamerSample/tree/master/sample01

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アドレスに応じて変更します。

<!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を動作させます。

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をインストールします。

$ 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を起動します

$ ./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で動作確認しても問題なく動作しました。

<!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
クライアントからの使いやすさ
サーバー(ラズパイ)の準備の手軽さ
映像の低遅延 ×

関連記事

ラズベリーパイのカメラを使ってリアルタイムに顔検出して年齢・性別判定する処理を試しました。

ラズパイ+Python+OpenCVでリアルタイムに顔検出して年齢・性別判定する

追記


気付いたらmjpeg-streamerが落ちてる時があったので、cronで監視して落ちてたら起動させます。

~/mjpg-streamer/mjpg-streamer-experimental 配下に

mjpg_check.sh

mjpg_reboot.sh

というシェルスクリプトを作成し以下を記述します。


/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

./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を動作させます。


$crontab -e
* * * * * /bin/sh ~/mjpg-streamer/mjpg-streamer-experimental/mjpg_check.sh

cron自体が起動しているかは以下で確認。


$ /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 で起動させます。

参考図書

ハイパフォーマンス ブラウザネットワーキング

ストリーミングは最終章に記載されていますが、その前提となるブラウザネットワークに関して体系的に学ぶことができます。

Real-Time Communication with WebRTC

洋書なので別の書籍である程度学習した後の方が良いと思いますが、WebRTCに関して詳細に学びたい方にはオススメです。Kindle版の方が比較的お得なようです。

参考にしたサイト

・RTSP

 https://qiita.com/zono_0/items/43fc89876977738de402

・GStreamer

 https://qiita.com/suo-takefumi/items/aba3db7d639a8b1a8981

・mjpeg-streamer

 https://note.com/agw/n/ne767158e323d

-javascript, RaspberryPi
-, , , ,

Copyright© ITエンジニアへの転身 , 2024 All Rights Reserved Powered by STINGER.