ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Raspberry Pi】Raspberry Piでカメラのライブストリーミングをやってみる

 ラズパイについて色々調べていたら、カメラを使ったライブストリーミング環境を構築している記事を見つけたのでそれをやってみた備忘録です。

 ほぼこちらの記事そのままなので、詳しい方法などはそちらを参照してください。

 では始めます。


1:Raspberry Piとカメラ
 今回自分が使ったRaspberry Piとカメラは以下の通りです。

Raspberry Pi 4 2GBモデル
 Raspberry Pi 4で一番安いモデルです。

Raspberry Pi カメラモジュール Rev 1.3
 リボンケーブルで接続するタイプのRaspberry Pi用のカメラモジュールです。今買うとしたらV2という新しいバージョンのカメラになっていると思いますが、古いこのタイプでもちゃんとカメラとして映るので大丈夫でした。
 ちなみにRaspberry Pi用のカメラモジュールを使っていますが、市販されているUSBで接続するタイプのカメラでも大丈夫だと思います。

 あとはディスプレイやマウス、キーボードなどを用意します。


2:カメラの確認
 まずはカメラがちゃんと認識されているかを確認します。以下のコマンドを実行して接続されているデバイスを確認します。

$ v4l2-ctl --list-device

 このコマンドが使えない場合は、以下のコマンドを実行してインストールします。

$ sudo apt-get install v4l-utils

「v4l2-ctl --list-device」を実行すると、以下のように接続されているデバイス一覧が表示されます。

$ v4l2-ctl --list-device
bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12

mmal service 16.1 (platform:bcm2835-v4l2):
        /dev/video0

 カメラを1台接続している場合は上記の「/dev/video0」がそのカメラのデバイスになっています。この表示がなければラズパイ側でカメラが認識されていないので、もう一度接続を確認してみてください。


3:FFmpeg、Nginxなどのインストール
 今回のカメラ映像ライブストリーミングの流れを簡単に言うと「カメラ映像→FFmpegH.264に変換→RTMPプロトコルでNginxサーバに送る→WebページでHLS形式で配信」という感じになっています。

 なのでRaspberry PiFFmpeg、Nginxをラズパイにインストールする必要があります。

 これらをインストールするために、以下のコマンドを実行します。

・パッケージリストの更新

$ sudo apt-get update

FFmpegのインストール

$ sudo apt-get install ffmpeg

・Nginxのインストール

$ sudo apt-get install nginx

・NginxにRTMPを対応させるモジュールをインストール

$ sudo apt-get install libnginx-mod-rtmp

 先にapt-get updateをやっておかないとインストールできない場合があるので、実行しておくのを忘れないようにしてください。


4:HLS配信の設定
 必要なもののインストールができたので、次は配信用の設定ファイルを記述していきます。

 以下のコマンドを実行してconfファイルをエディタで開きます。

$ sudo nano /etc/nginx/modules-available/rtmp-live.conf

 rtmp-live.confファイルの中身は以下のように記述します。各設定項目の詳しい説明はこの公式wikiを参照してください。

rtmp-live.conf

rtmp {                            # RTMPでの設定
        server {
                listen 1935;      # ポート番号
                chunk_size 4096;  # チャンクサイズ
                allow play all;   # 許可。play allなので全て再生を許可している。
                access_log /var/log/nginx/rtmp_access.log;  # アクセスログの保存パス

                application live {          # applicationの後の文字が名称がURLの一部になる。つまりrtmp://<ip address>/liveのようになる。
                        live on;            # ライブ配信を受け取る
                        hls on;             # ストリーミング形式をHLSにする
                        record off;         # 録画しない 
                        hls_path /tmp/live; # 配信用ファイル(.tsファイル)保存先
                        hls_fragment 1s;    # .tsファイルに区切る秒数
                }
        }
}

 ファイルの記述が終了したら、今度はシンボリックリンクを作成します。こうすることでNginxを起動させる毎に「rtmp-live.conf」ファイルが読み込まれるようになります。

$ cd /etc/nginx/modules-enabled
$ sudo ln -s ../modules-available/rtmp-live.conf ./99-rtmp-live.conf

 これでHLS配信の設定は完了です。


5:配信ファイルの保存場所をRAMにする
 4までの設定でも問題なく配信はできますが、今のままでは配信用の動画ファイルの一時保存先は「/tmp」になっています。つまりはSDカードに保存されるようになっているので、配信をすると配信用動画の一時保存と削除が大量に行われます。これではSDカードの寿命を縮めることにもなってしまうので、ラズパイ本体のメモリー領域であるRAMに保存するように設定します。

 まず以下のコマンドでfstabファイルをエディタで開きます。

$ sudo nano /etc/fstab

 エディタを開いたら以下の一文を追記します。

tmpfs    /tmp    tmpfs   defaults,noatime,mode=1777    0    0

 追記したらファイルを上書き保存します。

 ちなみに各項目は以下のようになっています。

1.device:マウントされるパーティション/デバイス。tmpfsはRAMディスク。
2.dir:マウントポイント。/tmpを指定。
3.type:ファイルシステムタイプ。RAMディスクなのでtmpfsを指定。
4.options:マウントオプション。mode=1777はファイル操作を行う設定。
5.dump:dumpでバックアップを取るかどうか。0はバックアップなし。
6.fsckfsckによるチェックの順番。0はチェックなし。

 これで/tmpファイルがRAM上に保存されるようになります。ちなみにラズパイを再起動させると自動的に削除されます。


6:Webページの準備
 続いて配信ファイルを表示させるWebページの準備をします。

 Webページは「/var/www/html」配置します。「cd /var/www/html」で移動して、そのディレクトリからライブ配信しているHLS動画を参照できるようシンボリックリンクを設定します。

$ cd /var/www/html
$ sudo ln -s /tmp/live live

 そして「/var/www/html」ディレクトリ内にindex.htmlファイルを作成します。

$ sudo nano /var/www/html/index.html

 HLSを表示させるライブラリはhls.jsなど色々ありますが、今回はVideo.jsというライブラリを使用します。index.htmlファイルの中身は以下のように記述します。

・index.html

<!DOCTYPE html>
<html lang="ja">
	<head>
		<title>Streaming Test</title>
		<!-- このスタイルシートを読み込まないと再生ボタンなどが表示されない -->
		<link href="https://vjs.zencdn.net/7.6.6/video-js.css" rel="stylesheet" />
	  </head>
	  <body>
		<h1>Movie Title</h1>
		<p>description</p>
		<video-js	
		  id="my-video"
		  controls
		  liveui="true"
		  preload="auto"
		  width="1280"
		  height="720"
		  data-setup="{responsive: true}"
		>
		  <source src="/live/stream.m3u8" type="application/x-mpegURL" />
		  <p class="vjs-no-js">
			To view this video please enable JavaScript, and consider upgrading to a web browser that
			<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
		  </p>
		</video-js>
		<script src="https://vjs.zencdn.net/7.6.6/video.js"></script>
	  </body>
</html>

 
 index.htmlを保存すればWebページの準備は完了です。

 Webページがちゃんと表示されるかはNginxを起動させてから確認します。

 以下のコマンドでNginxを再起動させます。

$ sudo systemctl restart nginx.service

 Nginxのプロセスがちゃんと動いているかは「ps aux | grep nginx」コマンドで確認します。

$ ps aux | grep nginx
root      3778  0.0  0.0  57776  1324 ?        Ss   14:56   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data  3779  0.5  0.3  58036  4716 ?        S    14:56   0:01 nginx: worker process
www-data  3780  0.0  0.1  57916  2844 ?        S    14:56   0:00 nginx: worker process
www-data  3781  0.0  0.1  57916  2844 ?        S    14:56   0:00 nginx: worker process
www-data  3782  0.0  0.1  57916  2844 ?        S    14:56   0:00 nginx: worker process
www-data  3783  0.0  0.1  57908  2908 ?        S    14:56   0:00 nginx: cache manager process
pi        3870  0.0  0.0   3916   560 pts/1    S+   15:00   0:00 grep --color=auto nginx

 Nginxの起動時にエラーが出たりプロセスが確認できない場合は「/var/log/nginx/error.log」を開いてエラーを確認してみてください。

$ cat /var/log/nginx/error.log

 Nginxの起動を確認できたらRaspberry Piのブラウザを開いてURLに「127.0.0.1」と打ち込みます。以下のような画面が表示されればOKです。
f:id:rikoubou:20200930150946p:plain


7:ライブ配信の確認
 ようやくライブ配信の確認です。

 ライブ配信をするにはffmpegを使いますが、コマンドが長くなるのでシェルファイルを記述し、そのファイルを実行するようにします。

 どこでも良いですが、homeディレクトリ直下に「mystreaming.sh」ファイルを作成します。

$ cd
$ nano mystreaming.sh

 シェルファイルの内容は以下のように記述して保存します。

・mystreaming.sh

#!/bin/bash
if pidof -x ffmpeg > /dev/null; then
    echo "FFmpeg is already running."
    exit 1
fi

ffmpeg \
    -f v4l2 -thread_queue_size 8192 -input_format yuyv422 \
    -video_size 1280x720 -framerate 30 \
    -i /dev/video0 \
    -c:v h264_omx -b:v 768k \
    -bufsize 768k -vsync 1 -g 10 \
    -f flv rtmp://localhost/live/stream

 簡単に説明すると、最初のif文ですでにffmpegが実行されているかを確認します。すでに他で実行されていた場合は何もせずに終了します。ffmpegライブ配信部分については、1280×720のサイズでフレームレートを30に設定しています。

 ここまで準備ができたら以下のコマンドでシェルファイルを実行します。ライブ配信を止めたい場合は「Ctrl+C」で終了させます。

$ sh mystreaming.sh

 エラーがなければffmpegのコマンドが実行されるので、その状態でもう一度Raspberry Piのブラウザを開いてURLに「127.0.0.1」と打ち込みます。

 再生ボタンが表示されるので、そのボタンをクリックするとカメラ映像のライブ配信が表示されます。ただ10秒ぐらい遅延があるかと思います。

 また「ip a」コマンドでRaspberry PiIPアドレスを確認してそのアドレスにアクセスすることで別のPCなどからでもライブ配信を確認できます。

$ ip a

 ちなみにライブ配信中に「/tmp/live/」ディレクトリの中を見てみると、以下のように.tsファイルがどんどん作成されています。この.tsファイルが「rtmp-live.conf」の「hls_fragment 」で設定した秒数で細切れになった動画ファイルとなっています。

$ sudo ls /tmp/live/
stream-339.ts  stream-347.ts  stream-355.ts  stream-363.ts  stream-371.ts  stream-379.ts  stream-387.ts  stream-395.ts
stream-340.ts  stream-348.ts  stream-356.ts  stream-364.ts  stream-372.ts  stream-380.ts  stream-388.ts  stream-396.ts
stream-341.ts  stream-349.ts  stream-357.ts  stream-365.ts  stream-373.ts  stream-381.ts  stream-389.ts  stream-397.ts
stream-342.ts  stream-350.ts  stream-358.ts  stream-366.ts  stream-374.ts  stream-382.ts  stream-390.ts  stream-398.ts
stream-343.ts  stream-351.ts  stream-359.ts  stream-367.ts  stream-375.ts  stream-383.ts  stream-391.ts  stream-399.ts
stream-344.ts  stream-352.ts  stream-360.ts  stream-368.ts  stream-376.ts  stream-384.ts  stream-392.ts  stream-400.ts
stream-345.ts  stream-353.ts  stream-361.ts  stream-369.ts  stream-377.ts  stream-385.ts  stream-393.ts  stream-401.ts
stream-346.ts  stream-354.ts  stream-362.ts  stream-370.ts  stream-378.ts  stream-386.ts  stream-394.ts  stream.m3u8


 以上がRaspberry Piでカメラのライブストリーミングをやる方法です。

 ほぼ参考資料のページ様の内容と同じですが、割と簡単にできて驚きました。

 HLSやVideo.js、ffmpegについては何もわかっていないのでそのあたりも掘り下げて色々カスタマイズできるようになるともっと色々面白いことができそうです。


・参考資料