Help us understand the problem. What is going on with this article?

Raspberry Pi 3 の標準カメラで撮影した動画をブラウザに配信する方法まとめ

More than 3 years have passed since last update.

はじめに

最近、Raspberry Pi 3 と CSI 接続の標準カメラモジュールを入手しました。

せっかくカメラも入手したので、カメラで撮影した動画をリアルタイムで、できれば遅延を減らして高fpsでブラウザから閲覧したいなと思って色々方法を試してみたので、まとめてみます。

なお Raspberry Pi 3 の OS は Raspbian Jessie が前提となります。

$ uname -a
Linux raspberrypi 4.4.45-v7+ #954 SMP Fri Jan 27 19:06:40 GMT 2017 armv7l GNU/Linux

配信方法1 - mjpg-streamer

この方法は motion jpeg で配信します。いろんなところで紹介されている標準的な方法だと思います。

インストール

$ 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

動画の配信

$ ./mjpg_streamer -o "./output_http.so -w ./www" -i "./input_raspicam.so -x 640 -y 480 -fps 30 -q 10"

-q は jpeg の画質指定で、1が最小100が最大です。こいつを小さくすると高レートで配信できます。↑の例だと 10 なので画質は無茶苦茶粗いですが、fps はけっこう出ます。遅延は回線によりますが、LAN内なら WiFi とかでもほぼリアルタイムで見られました。

動画の受信

ブラウザで http://[ラズパイのIP]:8080/ を開くだけです。

配信方法2 - uv4l-raspicam

mjpg-streamer と同じく、 motion jpeg での配信となります。デーモンとして動作するので、ちゃんと使うおうとするとちょっと設定が手間かも。

インストール

linux-projects.org のリポジトリを参照しますので、まずは apt-key で鍵を登録します。

$ curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -

登録できたら、/etc/apt/sources.list に以下を追加します。

deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ jessie main

その後、

$ sudo apt-get update
$ sudo apt-get install uv4l-webrtc uv4l-raspicam-extras

でインストール完了です。インストール完了後 uv4l_raspicam サービスが勝手に起動します。

動画の配信

本来は /etc/uv4l_raspicam/ 以下の設定を書き換えてサービスを起動すべきなのですが、説明が長くなるので端折ります。まずは、uv4l_raspicam サービスを止めます。

$ sudo service uv4l_raspicam stop

次にコマンドラインから uv4l を直接起動します。

$ uv4l --auto-video_nr --driver raspicam --encoding mjpeg --width 640 --height 480 --quality 15 --server-option '--port=9000'

動画の受信

ブラウザで http://[ラズパイのIP]:9000/stream/video.mjpeg を開くとストリームが見られます。

配信方法3 - gstreamer で h264動画 を HLS (MPEG-2 TS) 形式にして配信

gstreamer の tcpserversink 経由で動画ストリームをそのままブラウザに渡す(HTML5 タグのソースとして使う)という豪快な方法を紹介している記事がいくつか見つかります。HTTPプロトコルまるっきり無視な気がするけど、ブラウザから GET 来た時だけ HTTP 喋ったりするんですかね...?よく分かりません。

しかし、ラズパイが生成できる h264 ストリームをそのままvideoタグに突っ込んで再生できるブラウザはないようです。

しかたないので以下では h264 ストリームを gstreamer を使って HLS 化して配信します。この方法は遅延が数十秒になるのと最近のブラウザだと Android の Chrome あたりでしか再生できないのですが、いちおう参考ということで。

インストール

まずは gstreamer 本体をインストールします。

$ sudo apt-get install -y gstreamer1.0 gstreamer1.0-tools

gstreamer は raspivid コマンドの出力をそのままパイプで入力することも出来ますが、せっかくなので Raspberry Pi の標準カメラを直接入力ソースとして使える gst-rpicamsrc もインストールします。

$ git clone https://github.com/thaytan/gst-rpicamsrc.git
$ cd gst-rpicamsrc
$ ./autogen.sh --prefix=/usr --libdir=/usr/lib/arm-linux-gnueabihf/
$ make
$ sudo make install

生成したHLSファイル一式を配信するために Web サーバーがいるので、 nginx を入れます。

$ sudo apt-get install -y nginx

HLSファイルを /var/www/html/stream/ に生成するので mkdir します。

$ sudo mkdir /var/www/html/stream/

以下の内容でindex.html ファイルを /var/www/html/stream/index.html に置きます。

/var/www/html/stream/index.html
<!DOCTYPE html>
<html><head></head><body>
<video src="./stream/output.m3u8" width="640" height="480"/>
</body></html>

動画の配信

次のコマンドで、カメラ画像のストリーミングを開始します。

$ gst-launch-1.0 -v -e rpicamsrc ! video/x-h264,width=640,height=480,bitrate=800000 ! h264parse ! mpegtsmux ! hlssink max-files=8 target-duration=5 location=/var/www/html/stream/segment%05d.ts playlist-location=/var/www/html/stream/output.m3u8 playlist-root=./

動画の受信

ブラウザで http://[ラズパイのIP]/stream/ を開きます。

補足

gstreamer + Janus WebRTC Gateway という配信方法もあるようです。こちらは VP8 になるので Chrome 専用(だと思う)のと、 Raspberry Pi で VP8 エンコードはちょっと重いかな...と思って今回は試しておりません。

配信方法4 - h264-live-player

Javascript で h264 デコードして canvas タグ上で再生するというぶっちぎりアプローチです。最初ネタだと思ったんですが、PC はおろか iPhone 7の Safari でも普通に動いてしまいました。ラズパイ側では raspivid の出力を WebSocket 経由でブラウザに垂れ流すというシンプルな構成。ちなみに h264-live-player が使っている h264 デコーダは Broadway.js は Android のデコーダを emscripten でビルドしたものらしいです。

インストール

まず、nodejs をインストールします。普通に apt-get するとむちゃくちゃ古い nodejs が入ってしまうので、本家の記事に従って6系をインストールします。

$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
$ sudo apt-get install -y nodejs

次に h264-live-player をインストール

$ git clone https://github.com/131/h264-live-player
$ cd h264-live-player
$ npm install

動画の配信

以下を実行します。内部的には raspivid とウェブサーバーが起動してブラウザからの接続を待つ状態になります。

$ node server-rpi.js

動画の再生

ブラウザで http://${ラズパイのIP}:8080/ を開きます。

補足

ブラウザが WebSocket を切断したタイミングで server-rpi.js がクラッシュします。クラッシュした場合は raspivid のプロセスが残っているので、それを kill してから node server-rpi.js を再度実行する必要があります。

ちなみに切断時にクラッシュする現象は h264-live-player の lib/_server.js の 79行目 self.readstream.end() をコメントアウトすると抑えられます。

78:    socket.on('close', function() {
79:      self.readStream.end();
80:      console.log('stopping client interval');
81:    });

おわりに

低解像度なら mjpeg 形式の配信であまり困らないと思います。h264 はビットレートが安定するので突然のラグは少ない反面、ブロックノイズは目立つことがあります。

再生遅延については画質と解像度によって mjpeg と h264 どちらが良いかは一概に言えない印象なので、色々設定を変えながら両方とも試すのが良いかなと思います。

okaxaki
薄毛のカリスマを目指しているうちにハゲてしまったおっさんプログラマです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした