Linux活用レシピ > 家電の制作 > RaspberryPiでライブストリーミング環境を構成
このページでは、「RaspberryPi」と、それで動作するOS「Raspbian」で、安価にリアルタイム動画を配信する環境(ライブストリーミング環境)を構成するレシピを紹介します。


RaspberryPiを使ったライブストリーミング環境の製作
ライブ配信サーバーの構築


ここでは、Raspberry Pi自体をライブ配信サーバーとして構成する方法をレシピとして紹介します。
日本語化したOS「Raspbian」にnginxでWebサーバーを構成し、Webカメラの画像をネットワークにリアルタイムストリーミングで配信する内容になります。

目次



1. パッケージインストール

まずは「Raspberry Pi」にWebカメラをUSBで接続し、OS「Raspbian」を起動して、必要なパッケージをインストールしていきます。

    デスクトップ画面の上のメニューから以下の通り赤枠の部分をクリックしてコンソールを起動します。


    以下のコマンドで、リポジトリを最新にします。
    pi@raspberrypi:~ $ sudo apt-get update[ENTER]

    次に、以下のコマンドで、今回Webサーバーを構成する「nginx」はじめ、必要なモジュールをインストールします。
    pi@raspberrypi:~ $ sudo apt install nginx php-fpm \
     libnginx-mod-rtmp apache2-utils ffmpeg [ENTER]
    ※途中インストールするかどうか聞かれますので「Y」を入力して[ENTER]キーで処理を進めてください。

    コンソールが返ってくれば必要モジュールをインストールは完了です。

▲目次



2. Webサーバー設定

今回配信に使用するWebサーバー「nginx」の設定を行っていきます。

    まずは、以下のコマンドでnginxのバージョンを確認し、問題なくインストールされているか確認します。
    pi@raspberrypi:~ $ nginx -v[ENTER]

    以下の通りバージョン情報が返ってきます。
    nginx version: nginx/1.14.2
    

    次に、以下のコマンドでnginxが動作していることを確認します。
    pi@raspberrypi:~ $ systemctl status nginx[ENTER]

    以下の通り応答があり、正常に起動していることが分かります。
    nginx.service - A high performance web server and a reverse proxy server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: en
    Active: active (running) since Sun 2020-03-01 16:30:33 JST; 2min 27s ago
    Docs: man:nginx(8)
    Main PID: 6654 (nginx)
    Tasks: 5 (limit: 2200)
    Memory: 4.8M
    CGroup: /system.slice/nginx.service
    ├─6654 nginx: master process /usr/sbin/nginx -g daemon on; master_pro
    ├─6655 nginx: worker process
    ├─6656 nginx: worker process
    ├─6657 nginx: worker process
    └─6658 nginx: worker process

    3月 01 16:30:33 raspberrypi systemd[1]: Starting A high performance web server
    3月 01 16:30:33 raspberrypi systemd[1]: Started A high performance web server a

    次に、nginx のPHP設定を行います。
    まず、既存設定をバックアップし、編集していきます。
    pi@raspberrypi:~ $ sudo cp -ip /etc/nginx/sites-available/default \
    /etc/nginx/sites-available/default.old[ENTER]
    pi@raspberrypi:~ $ sudo vi /etc/nginx/sites-available/default[ENTER]
    

    index部分について変更前が以下で、
            # Add index.php to the list if you are using PHP
            index index.html index.htm index.nginx-debian.html;
    

    赤文字の部分を追記します。
            # Add index.php to the list if you are using PHP
            index index.php index.html index.htm index.nginx-debian.html;
    

    また、「location ~ \.php$」の部分について、赤文字のコメントを外していきます。
            #location ~ \.php$ {
            #       include snippets/fastcgi-php.conf;
            #
            #       # With php-fpm (or other unix sockets):
            #       fastcgi_pass unix:/run/php/php7.3-fpm.sock;
            #       # With php-cgi (or other tcp sockets):
            #       fastcgi_pass 127.0.0.1:9000;
            #}
    

    以下の通りになります。
            location ~ \.php$ {
                   include snippets/fastcgi-php.conf;
    
                   # With php-fpm (or other unix sockets):
                   fastcgi_pass unix:/run/php/php7.3-fpm.sock;
                   # With php-cgi (or other tcp sockets):
            #       fastcgi_pass 127.0.0.1:9000;
            }
    

    さらに、「location ~ /\.ht {」の部分について、赤文字のコメントを外していきます。
            #location ~ /\.ht {
            #       deny all;
            #}
    

    以下の通りになります。
            location ~ /\.ht {
                   deny all;
            }
    

    以上で保存して、nginx のPHP設定が完了しましたので、以下のコマンドでnginxを再起動します。
    pi@raspberrypi:~ $ sudo systemctl daemon-reload[ENTER]
    pi@raspberrypi:~ $ sudo systemctl restart nginx[ENTER]
    

    テストファイルを作成し確認を行います。
    pi@raspberrypi:~ $ sudo vi /var/www/html/index.php[ENTER]
    

    以下の通りテストコードを記載し保存します。
    <?php 
        phpinfo();
    ?>
    

    ブラウザで、「http://raspberrypiのIPアドレス/」に接続し、以下のような画面が出ればPHPは機能しています。

▲目次



3. デバイス確認

Webカメラのデバイス確認(認識されているかどうかの確認)を行っていきます。
    コンソールから以下の通り入力し、「カメラ」が認識されているか確認します。
    pi@raspberrypi:~ $ v4l2-ctl --list-device[ENTER]
    

    以下の通り表示されますので、この中に下線で示している「USB Camera(/dev/video0)」が表示されていれば認識されていることが分かります。
    bcm2835-codec-decode (platform:bcm2835-codec):
    	/dev/video10
    	/dev/video11
    	/dev/video12
    
    USB_Camera: USB_Camera (usb-3f980000.usb-1.1.2):
    	/dev/video0
    	/dev/video1
    


    次にコンソールから以下の通り入力し、「マイク」が認識されているか確認します。
    pi@raspberrypi:~ $ arecord -l[ENTER]
    

    以下の通り表示されますので、この中に下線で示している「カード 1:」が表示されていれば認識されていることが分かります。
    **** ハードウェアデバイス CAPTURE のリスト ****
    カード 1: USBCamera [USB_Camera], デバイス 0: USB Audio [USB Audio]
      サブデバイス: 1/1
      サブデバイス #0: subdevice #0
    


    最後に実際に録画してみて、きっちりカメラとマイクが機能しているか確認しましょう。

    まず、以下の通り録画データを保存する場所を確保しその場所にカレントディレクトリを変更します。
    pi@raspberrypi:~ $ mkdir -p ~/public_html/temp[ENTER]
    pi@raspberrypi:~ $ cd /var/www/html/[ENTER]
    pi@raspberrypi:/var/www/html $ sudo ln -s ~/public_html/temp .[ENTER]
    pi@raspberrypi:/var/www/html $ cd tmp[ENTER]
    pi@raspberrypi:/var/www/html/tmp $
    


    では以下のコマンドで「ffmpeg」を使って録画してみます。
    pi@raspberrypi:/var/www/html/tmp $ ffmpeg -f alsa -ac 2 -i hw:1 -f v4l2 \
     -s 640x480 -i /dev/video0 ~/public_html/temp/output.mpg[ENTER]
    
      ※カード1を使用するため、「hw:1」を指定します。「-ac 2」でチャネルを指定しています。なお、「-ac 1 」を指定すると以下のエラーが出たので、「-ac 2」としました。
      cannot set channel count to 1 (Invalid argument)
      hw:1: Input/output error
      

    なお、デバイスのチャネルを気にせず、オールマイティで行けそうなパラメータは、チャネル番号を指定するパラメータ「-ac <チャネル番号>」をなくし、オーディオデバイスの指定を「hw:1」から「plughw:1」に変更した以下の内容が使えそうなので、本レシピではこれに統一します。
    pi@raspberrypi:/var/www/html/tmp $ ffmpeg -f alsa -i plughw:1 -f v4l2 \
     -s 640x480 -i /dev/video0 ~/public_html/temp/output.mpg[ENTER]
    
    すると、以下の通り録画の進行状況が表示されていきます。
    frame=  22 fps=0.0 q=4.9 size=  148kB time=00:00:00.63 bitrate=1914.3kbits/s
    frame=  49 fps= 48 q=8.6 size=  260kB time=00:00:01.53 bitrate=1389.1kbits/s
    frame=  76 fps= 49 q=13.4 size=  356kB time=00:00:02.43 bitrate=1198.5kbits/
    frame= 106 fps= 51 q=15.3 size=  462kB time=00:00:03.43 bitrate=1102.3kbits/
    frame= 136 fps= 53 q=13.9 size=  546kB time=00:00:04.43 bitrate=1008.9kbits/
    frame= 151 fps= 49 q=12.3 size=  610kB time=00:00:04.93 bitrate=1012.9kbits/
    frame= 166 fps= 46 q=12.5 size=  650kB time=00:00:05.43 bitrate= 980.0kbits/
    

    撮影中は音や声を出して、それらがしっかり動画に入るようにしましょう。
    ほどよいところで「Ctrl」+「C」キーで録画を止めます。と以下の通りの表示になりコンソールが戻ってきます。
    video:496kB audio:317kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.027768% Exiting normally, received signal 2.
    pi@raspberrypi:/var/www/html/tmp $ 
    

    これで録画ができたと思いますので、ブラウザで
    「http://raspberrypiのIPアドレス/temp/output.mpg」
    に接続してください。

    動画のダウンロード後、再生アプリの指定を行えば、動画が再生され始めます。
    画像に加え音や声も入っていれば、Webカメラの「カメラ」と「マイク」は正常に機能していることが確認できたことになります。

▲目次



4. ライブストリーミング用の環境設定

ライブストリーミングサーバーの環境を整えていきます。
    ストリーミングデータの保存場所をRAM(共有メモリ)に作成します。
    pi@raspberrypi:~ $ sudo mkdir -p /var/www/html/live/[ENTER]
    pi@raspberrypi:~ $ cd /var/www/html/live/[ENTER]
    pi@raspberrypi:/var/www/html/live $ sudo ln -s /dev/shm hls[ENTER]
    
    これは、SDカード上に作らないことで、SDカードの書き込み回数に伴う寿命の低下を極力回避する目的があります。

    次に以下のコマンドで「hls.min.js」を取得します。
    ※このレシピではCDNを使って動的に取得する方法(後述のindex.html)を取りますので、実際にはこの操作は不要です。
    pi@raspberrypi:~ $ sudo curl \
     https://cdn.jsdelivr.net/hls.js/latest/hls.min.js \
     -o /var/www/html/hls.min.js[ENTER]
    


    次にHLS 配信用 index.htmlをルートディレクトリ「/var/www/html/」に作成します。
    pi@raspberrypi:~ $ vi /var/www/html/index.html[ENTER]
    

    以下の通り記載し保存します。
    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="utf-8"/>
      <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    </head>
    <body>
      <video id="video" controls width="100%"></video>
      <script>
        if(Hls.isSupported()) {
          var video = document.getElementById('video');
          var hls = new Hls();
          hls.loadSource('live/hls/stream.m3u8');
          hls.attachMedia(video);
          hls.on(Hls.Events.MANIFEST_PARSED,function() {
          video.play();
        });
       }
      </script>
    <p>
      iPhoneなどで再生されない場合は、<a href="live/hls/stream.m3u8">
    こちら</a>をクリック。
    </p>
    </body>
    </html>
    


    次にnginxのrtmp用コンフィグレーションを作成します。
    pi@raspberrypi:~ $ vi sudo vi /etc/nginx/conf.d/rtmp[ENTER]
    

    以下の通り記載し保存します。
    rtmp {
        server {
            listen 1935;
            chunk_size 4096;
            allow play all;
            access_log /var/log/nginx/rtmp_access.log;
            application live {
                live on;
                hls on;
                record off;
                hls_path /var/www/html/live/hls;
                hls_fragment 1s;
                hls_type live;
            }
        }
    }


    次に、上記rtmpコンフィグレーションを読み込むよう、nginxの設定ファイルの末尾に以下のコマンドで、1行足します。
    pi@raspberrypi:~ $ sudo sh -c \
    "echo \"include /etc/nginx/conf.d/rtmp;\" >> /etc/nginx/nginx.conf"[ENTER]
    


    8090ポートでアクセスを待ち受けるように設定します。ポート番号はなんでもいいです。
    pi@raspberrypi:~ $ sudo vi /etc/nginx/conf.d/default.conf[ENTER]
    

    以下の通り編集します。
    server {
        listen 8090;
        proxy_set_header   X-Forwarded-For     $proxy_add_x_forwarded_for;
        access_log /var/log/nginx/access.log combined;
        error_log /var/log/nginx/error.log warn;
        location = /favicon.ico {
            access_log off;
            empty_gif;
            expires 30d;
        }
        location / {
            #auth_basic "Web Cam Streaming";
            #auth_basic_user_file /var/www/.htpasswd;
            root /var/www/html;
            index index.html;
            set_real_ip_from    127.0.0.1;
            real_ip_header      X-Forwarded-For;
        }
    }
    ※Basic認証は動作が確認できるまで無効にしておきます。後で設定。

    以上でnginxの設定は完了です。以下のコマンドで再起動しておきます。
    pi@raspberrypi:~ $ sudo systemctl daemon-reload[ENTER]
    pi@raspberrypi:~ $ sudo systemctl restart nginx[ENTER]
    
▲目次



5. ストリーミングの開始・停止スクリプト

簡単にストリーミングの開始・停止ができるようにシェルスクリプトを作成します。
    まず、シェルスクリプト用にフォルダを作っておきましょう。
    pi@raspberrypi:~ $ mkdir ~/scripts/[ENTER]
    


    開始スクリプトを作成します。
    pi@raspberrypi:~ $ vi ~/scripts/streaming-start.sh[ENTER]
    

    以下の通り編集します。赤文字部分は画面サイズです。また、青文字部分はフレームレート(1秒間の動画で見せる静止画の枚数「コマ数」)です。
    #!/bin/bash
    NUM=`ps aux | grep ffmpeg | grep -v grep | wc -l`
    if [ $NUM -gt 0 ]; then
            echo "Already running."
            exit
    fi
    ffmpeg \
            -f alsa -thread_queue_size 8192 \
            -i plughw:1 -f v4l2 \
            -thread_queue_size 8192 \
            -input_format yuyv422 -video_size 640x480 \
            -framerate 30 -i /dev/video0 -c:v h264_omx \
            -b:v 768k -bufsize 768k -vsync 1 -g 16 \
            -c:a aac -b:a 128k -ar 44100 -af "volume=5dB" \
            -f flv rtmp://localhost/live/stream > /dev/null 2>&1 </dev/null &
    
    ここで、Webカメラが入力可能な画面サイズと、各画面サイズ毎のフレームレートは、以下のコマンドで確認できますので、その範囲で任意に指定してください。
    pi@raspberrypi:~ $ v4l2-ctl -d /dev/video0 --list-formats-ext[ENTER]
    
    以下の通り、各画面サイズとその際のフレームレートが表示されます。
    上記スクリプト内のffmpegで指定している記録フォーマットは「yuyv422」で指定していますので、下記の下線部の「'YUYV' (YUYV 4:2:2)」区画に表示されている、各画面サイズ毎のフレームレートを使用してください。
    ioctl: VIDIOC_ENUM_FMT
    	Type: Video Capture
    
    	[0]: 'YUYV' (YUYV 4:2:2)
    		Size: Discrete 640x480
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 160x120
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 176x144
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 320x240
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 352x288
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 800x600
    			Interval: Discrete 0.100s (10.000 fps)
    		Size: Discrete 1280x720
    			Interval: Discrete 0.125s (8.000 fps)
    		Size: Discrete 1920x1080
    			Interval: Discrete 0.200s (5.000 fps)
    	[1]: 'MJPG' (Motion-JPEG, compressed)
    		Size: Discrete 640x480
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 160x120
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 176x144
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 320x240
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 352x288
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 800x600
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 1280x720
    			Interval: Discrete 0.033s (30.000 fps)
    		Size: Discrete 1920x1080
    			Interval: Discrete 0.033s (30.000 fps)
    
    フレームレートは数字が大きいほどなめらかですが、画面サイズが大きくなるごとに、記録できるフレームレートは小さくなります。これはWebカメラの性能によりますので、お手持ちのWebカメラで実際に確認してください。


    なお、Webカメラのマイクではなく、「~./Music」(ホームディレクトリのMusic)ディレクトリに複数の音楽ファイル(mp3フォーマット)を置いておき、それをBGMとして順番に流す場合は、以下の「緑の部分のコード」の通りスクリプトを変更してください。
    #!/bin/bash
    NUM=`ps aux | grep ffmpeg | grep -v grep | wc -l`
    if [ $NUM -gt 0 ]; then
            echo "Already running."
            exit
    fi
    ffmpeg \
            -re -f concat -thread_queue_size 8192 \
            -safe 0 -i <(for file in ~/Music/*.mp3 ; \
                    do echo file "$file" ; done) \
            -f v4l2 -thread_queue_size 8192 \
            -input_format yuyv422 -video_size 640x480 \
            -framerate 30 -i /dev/video0 -c:v h264_omx \
            -b:v 768k -bufsize 768k -vsync 1 -g 16 \
            -c:a aac -b:a 128k -ar 44100 -af "volume=5dB" \
            -f flv rtmp://localhost/live/stream > /dev/null 2>&1 </dev/null &
    
    ※Musicディレクトリに保存するMP3ファイルのフォーマットはすべて同じにしてください。


    また、「~./Music」ディレクトリの音楽ファイルを指定回数ループ(以下では10回)させる場合は、以下の「緑の部分のコード」の通りスクリプトを変更してください。
    #!/bin/bash
    NUM=`ps aux | grep ffmpeg | grep -v grep | wc -l`
    if [ $NUM -gt 0 ]; then
            echo "Already running."
            exit
    fi
    ffmpeg \
            -re -f concat -thread_queue_size 8192 \
            -safe 0 -i <(for i in {1..10};do for file in ~/Music/*.mp3 ; \
                    do echo file "$file" ; done; done) \
            -f v4l2 -thread_queue_size 8192 \
            -input_format yuyv422 -video_size 640x480 \
            -framerate 30 -i /dev/video0 -c:v h264_omx \
            -b:v 768k -bufsize 768k -vsync 1 -g 16 \
            -c:a aac -b:a 128k -ar 44100 -af "volume=5dB" \
            -f flv rtmp://localhost/live/stream > /dev/null 2>&1 </dev/null &
    


    さらに、ランダム再生する場合は、以下の「緑の部分のコード」の通りスクリプトを変更してください。
    #!/bin/bash
    NUM=`ps aux | grep ffmpeg | grep -v grep | wc -l`
    if [ $NUM -gt 0 ]; then
            echo "Already running."
            exit
    fi
    ffmpeg \
            -re -f concat -thread_queue_size 8192 \
            -safe 0 -i <(for i in {1..10};do for file in \
                    `ls ~/Music/*.mp3|sort -R` ; \
                    do echo file "$file" ; done; done) \
            -f v4l2 -thread_queue_size 8192 \
            -input_format yuyv422 -video_size 640x480 \
            -framerate 30 -i /dev/video0 -c:v h264_omx \
            -b:v 768k -bufsize 768k -vsync 1 -g 16 \
            -c:a aac -b:a 128k -ar 44100 -af "volume=5dB" \
            -f flv rtmp://localhost/live/stream > /dev/null 2>&1 </dev/null &
    


    次に、終了スクリプトを作成します。
    pi@raspberrypi:~ $ vi ~/scripts/streaming-stop.sh[ENTER]
    
    以下の通り編集します。
    #!/bin/bash
    sudo killall -INT ffmpeg
    


    作成したスクリプトに実行権を付与します。
    pi@raspberrypi:~ $ chmod +x ~/scripts/streaming-*.sh[ENTER]
    

    以上でストリーミングのスクリプトは完成です。
▲目次



6. ストリーミングの開始と確認そして停止

ストリーミングを開始してみて、Raspberry Pi のNginxがサービスするWebサーバーで、Webカメラで撮影した動画のリアルタイム配信ができるか確認します。
    以下の通り、スクリプトを実行しストリーミングを開始します。
    pi@raspberrypi:~ $ ~/scripts/streaming-start.sh[ENTER]
    

    これでストリーミングが開始できていると思いますので、ブラウザで
    「http://raspberrypiのIPアドレス:8090/」
    に接続してください。

    どうですか。少し遅延はあるもののきれいにリアルタイム配信されていませんか?

    なお、音声がはおることがありますので、Webカメラのそばに再生するパソコンがある場合は、離して再生するかヘッドセットで確認してください。

    動作が確認できれば停止してください。
▲目次



7. BASIC認証をかける

誰でも動画が閲覧できないよう、IDとパスワードで保護します。
    以下の通り、「ユーザー名」を指定して、そのパスワードをファイルに登録します。
    以下の例ではユーザー名を「username」としています。
    pi@raspberrypi:~ $ sudo htpasswd -c /var/www/.htpasswd username[ENTER]
    

    次に、/etc/nginx/conf.d/default.confを編集します。
    pi@raspberrypi:~ $ sudo vi /etc/nginx/conf.d/default.conf[ENTER]
    

    当初コメントアウトしていた/etc/nginx/conf.d/default.confの以下の2行の赤文字のコメント(#を消して保存)します。
            #auth_basic "Web Cam Streaming";
            #auth_basic_user_file /var/www/.htpasswd;
    

    以下の通りにして、保存します。
            auth_basic "Web Cam Streaming";
            auth_basic_user_file /var/www/.htpasswd;
    

    さらに、Nginxを以下の通り再起動します。これで、BASIC認証がかります。
    pi@raspberrypi:~ $ sudo systemctl daemon-reload[ENTER]
    pi@raspberrypi:~ $ sudo systemctl restart nginx[ENTER]
    

    ブラウザで
    「http://raspberrypiのIPアドレス:8090/」
    に接続してください。

    IDとパスワードが要求されますので、入力したユーザー名パスワードで、コンテンツが参照できます。
▲目次



8. マイク設定

マイクの入力の音量を変更します。
    以下のコマンドでミキサーを開きます。
    pi@raspberrypi:~ $ alsamixer[ENTER]
    

    以下の画面が開きますので、


    F6キーでサウンドカードの一覧を開き

    「USB_Camera」選択します



    F4キーで録音音量調整(マイクボリューム調整)を行います。

    上矢印キーで増音、下矢印キーで減音となります。

    ライブ配信しながら調整可能です。

▲目次