ラズパイカメラでFFmpegを使ってライブストリーミング【HLS】

この記事では、Raspberry Pi(ラズパイ)に取り付けたカメラで撮影した映像を、リアルタイムで外部のブラウザから確認できるようなストリーミングサーバーの構築を行っていく。ただし、マイクは取り付けていないので音声は対象外となる。

前回はGStreamerを使ったが、今回はFFmpegを使ってRaspberry PiからHTTP Live Streaming(HLS)配信できるようにしていく。配信といってもYouTube Liveやニコ生配信ではなく、あくまでもローカルエリア内でのストリーミングとなる。なお、Raspberry Piでカメラを使えるようにするまでの設定は済んでいるものとして、この記事では説明を省略する。

GStreamerバージョンはこちら

FFmpegのインストール

今回使用した環境は以下の通り。

環境

項目バージョン
ラズパイRaspberry Pi3 Model B+
カメラモジュールOV5647
OSRaspbian 9.13
Python2.7.13/3.7.0
FFmpegのコンパイルや処理でCPUを使うので、必ずRaspberry Piにヒートシンクをつけておこう。

また、こちらの記事を参考にあらかじめラズパイでカメラを使えるようにしておこう。

カメラモジュールの設定方法はこちらの記事を参考

カメラモジュールを/dev/video0に認識させておこう

FFmpegのインストール

それではRaspberry PiにFFmpegをインストールする。次のコマンドで簡単にインストールできる。

$ sudo apt -y install ffmpeg

FFmpegの公式サイト

こちらの環境では、こんな感じでインストールが完了している。

$ ffmpeg --version
ffmpeg version 3.2.15-0+deb9u1 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 6.3.0 (Raspbian 6.3.0-18+rpi1+deb9u1) 20170516
  configuration: --prefix=/usr --extra-version=0+deb9u1 --toolchain=hardened --libdir=/usr/lib/arm-linux-gnueabihf --incdir=/usr/include/arm-linux-gnueabihf --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libebur128 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  libavutil      55. 34.101 / 55. 34.101
  libavcodec     57. 64.101 / 57. 64.101
  libavformat    57. 56.101 / 57. 56.101
  libavdevice    57.  1.100 / 57.  1.100
  libavfilter     6. 65.100 /  6. 65.100
  libavresample   3.  1.  0 /  3.  1.  0
  libswscale      4.  2.100 /  4.  2.100
  libswresample   2.  3.100 /  2.  3.100
  libpostproc    54.  1.100 / 54.  1.100

FFmpegでHLS動画の作成

FFmpegのインストールができたら、HLS動画の作成をテストしてみよう。今回はソフトウェアエンコーディングとなるので libx264 を指定している。

$ ffmpeg -f v4l2 -thread_queue_size 16384 -s 640x480 -vsync -1 -i /dev/video0 \
  -c:v libx264 -b:v 1000k -bufsize 1000k \
  -flags +cgop+loop-global_header \
  -bsf:v h264_mp4toannexb \
  -f segment -segment_format mpegts -segment_time 10 -segment_list stream.m3u8 segment%06d.ts

上記コマンドを実行すれば、.m3u8ファイルと .tsファイルができているはず。.tsファイルが、映像や音声データが含まれている動画ファイルであり、それを順番管理しているテキストファイルが.m3u8ファイルである。

ブラウザから動画を閲覧できるかテスト

最後にパソコンのウェブブラウザからラズパイへアクセスして、動画が再生できるかテストしてみよう。

PythonでWebサーバーを作成

前回と同様、Pythonで簡易的なWebサーバーを作った。このプログラムをPython3で実行すると、ウェブブラウザから http://<ラズパイのIPアドレス>:5555 へアクセスできるようになる。

from http.server import HTTPServer, SimpleHTTPRequestHandler
import os
import ipget # $ sudo pip3 install ipget==0.0.3


os.chdir("./www")
a = ipget.ipget()
ip, bit = a.ipaddr("eth0").split('/')
port = 5555

httpd = HTTPServer(('', port), SimpleHTTPRequestHandler)
print('HTTPServer began -> http://{}:{}'.format(ip, port))
httpd.serve_forever()

Videoタグを使ったHTMLファイルを用意

次の内容のHTMLファイルを用意した。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>HTTP Live Streaming Test</title>
  </head>
  <body>
      <h1>HTTP Live Streaming Test</h1>
      <video width="640" 
             height="360" 
             src="stream.m3u8" 
             preload="none" 
             onclick="this.play()" 
             controls />
  </body>
</html>

ディレクトリ構成

こちらでは、次のディレクトリ構成となっているので参考に。

$ pwd
/home/pi/ffmpeg

$ tree
.
|-- hls.sh
|-- apps_item.html~
|-- server.py
`-- www
    |-- apps_item.html
    |-- segment000000.ts
    |-- segment000001.ts
    |-- segment000002.ts
    |-- segment000003.ts
    `-- stream.m3u8

HLSサーバーのシェルスクリプト

WebサーバーとFFmpegの実行を簡単にできるよう、シェルスクリプトを作ってみたので参考に。

#!/bin/sh
python3 server.py > /dev/null 2>&1 &

cd www
rm -Rf *.m3u8 *.ts

ffmpeg -f v4l2 -thread_queue_size 16384 -s 640x480 -vsync -1 -i /dev/video0 \
  -c:v libx264 -b:v 1000k -bufsize 1000k \
  -flags +cgop+loop-global_header \
  -bsf:v h264_mp4toannexb \
  -f segment -segment_format mpegts -segment_time 10 -segment_list stream.m3u8 segment%06d.ts

ちなみに上記シェルは ctrl + c で終了できるが、server.py だけはバックグラウンドで動き続けているため、$ ps -x でPIDを探して $ kill PID する。

以上を実行してテストしたところ、MacのSafariからは映像が確認できたがChromeからは映像を見ることができなかった。それもそのはず、HTTPリクエストを確認するとChromeでは.tsファイルへのリクエストが投げられていない。

Safari(macOS)

SafariからHLS動画のHTTPリクエスト
SafariからHLS動画のHTTPリクエスト

Chrome(macOS)

ChromeからHLS動画のHTTPリクエスト
ChromeからHLS動画のHTTPリクエスト

HLSのブラウザ対応状況

さらに調べると、そもそもMacのChromeではHLS再生にデフォルト対応していないことがわかった。

HLSの対応状況
HLSの対応状況

ただし、hls.jsライブラリを使うことで、ChromeでもHLS動画の再生が可能なようだ。こちらはそのうち試してみたい。とりあえず、前回のGStreamerでは再生できなかったmacOSのSafariでも、FFmpegでなら再生できたので良しとしよう。

今後の課題

映像がptpt止まってしまう。
ChromeでのHLS動画再生対応。
Raspberry Piのハードウェアデコーダを使った動画変換。

この記事で扱った関連製品はこちら

HiLetgo OV5647 5MP Raspberry Pi 3 カメラ OV5647 HDカメラモジュール Raspberry Pi に対応 A/B+/2 モデルB ケーブル
HiLetgo OV5647 5MP Raspberry Pi 3 カメラ OV5647 HDカメラモジュール Raspberry Pi に対応 A/B+/2 モデルB ケーブル

OV5647 Camera Module センサータイプ:OV5647色CMOS QSXGA(5メガピクセル) センサーサイズ:3.67*2.74mm(1/4インチフォーマット) ピクセル計算:2592*1944, ピクセルサイズ:1.4*1.4μm

Amazon
Raspberry Pi Zero W - ヘッダー ハンダ付け済み - ラズベリー・パイ ゼロ W ワイヤレス
Raspberry Pi Zero W - ヘッダー ハンダ付け済み - ラズベリー・パイ ゼロ W ワイヤレス

Amazon
正規代理店商品 Raspberry Pi 4 Model B (8GB) made in UK element14製 技適マーク入
正規代理店商品 Raspberry Pi 4 Model B (8GB) made in UK element14製 技適マーク入

Amazon

Raspberry Piの参考書

Raspberry Pi クックブック 第2版 (Make:PROJECTS)
Raspberry Pi クックブック 第2版 (Make:PROJECTS)

本書は、全世界で多くのユーザーの支持を集めているマイコンボード「Raspberry Pi」を使いこなすためのレシピ集です。ハードウェアの基本、オペレーティングシステムの使い方、ネットワーク接続、Pythonプログラミングの基本を紹介した上デ、実際の作品製作に必要になる、高度なPythonプログラミング、GPIO(汎用入出力)、モーター、センサー、ディスプレイなどの使い方へと解説を進めていきます。

Amazon
写真や図解でよくわかる ラズパイZeroを使い倒す本 Raspberry Pi Zero/Zero W対応
写真や図解でよくわかる ラズパイZeroを使い倒す本 Raspberry Pi Zero/Zero W対応

本書ではRaspberry Pi Zero / Zero Wの概要から必要な周辺機器の説明、OSの導入やセットアップなどといった準備、そしてLinuxに初めて触れる人に向けてLinuxの基礎やシェルの操作などを解説しています。また、準備が整ったら実際に電子部品をRaspberry Pi Zero / Zero Wで制御する方法も解説しました。

KindleAmazon
Raspberry Pi ZeroによるIoT入門- Zero W 対応
Raspberry Pi ZeroによるIoT入門- Zero W 対応

本書は、大人から子供まで、初心者の方でも、ラズパイZeroとラズパイZero WをIoTのデバイスとして使いこなせるようになることを目的とした入門書です。また、ラズパイZeroとラズパイZero WをUSBケーブル1本でパソコンに接続できる便利な「Zero over USB」について、日本で初めて詳しく解説しました。

Amazon

最後まで読んでいただきありがとうございました。

「この記事が参考になったよ」という方は、ぜひ記事をシェアをしていただけるととても嬉しいです。

今後も有益な記事を書くモチベーションにつながりますので、どうかよろしくお願いいたします。↓↓↓↓↓↓↓

あなたにおすすめ