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

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

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

GStreamerバージョンはこちら

ニコ生などへ配信したい場合はこちら

HiLetgo OV5647 5MP Raspberry Pi  カメラ OV5647 HDカメラモジュール
HiLetgo OV5647 5MP Raspberry Pi カメラ OV5647 HDカメラモジュール
Amazon

FFmpegのインストール

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

環境

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

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

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

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

ラズパイ用カメラモジュール

HiLetgo OV5647 5MP Raspberry Pi  カメラ OV5647 HDカメラモジュール
HiLetgo OV5647 5MP Raspberry Pi カメラ OV5647 HDカメラモジュール
Amazon

用途によってはケースに入った製品の方が使い勝手がよいかもしれない。

For raspberry pi カメラモジュール 5MP 感光チップOV5647センサー
For raspberry pi カメラモジュール 5MP 感光チップOV5647センサー
Amazon

また、ズーム機能付だったり、赤外線で夜間も撮影できるカメラモジュールもある。

Kuman カメラモジュール Raspberry Pi用 日中/夜間モード ズームレンズ
Kuman カメラモジュール Raspberry Pi用 日中/夜間モード ズームレンズ
Amazon
Kuman カメラモジュール Raspberry Pi用 夜間 赤外線可視 ラズベリーパイ
Kuman カメラモジュール Raspberry Pi用 夜間 赤外線可視 ラズベリーパイ
Amazon

動画など重い処理をラズパイで行う場合、CPUが発熱して本体が壊れる恐れがある。ヒートシンクや放熱性のあるケースに入れて必ず熱対策をしよう。

過去にラズパイを壊してしまったことがある。

Geekworm Raspberry Pi4 B 用アーマー金属ケース パッシブ冷却/シェル熱放散(ファン無し)
Geekworm Raspberry Pi4 B 用アーマー金属ケース パッシブ冷却/シェル熱放散(ファン無し)
Amazon
最新 Raspberry Pi 4 ケース, 超薄型アルミニウム合金ケース+ヒートシンク+ 35x35x10 冷却大超静音ファン
最新 Raspberry Pi 4 ケース, 超薄型アルミニウム合金ケース+ヒートシンク+ 35x35x10 冷却大超静音ファン
Amazon

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
|-- item_apps.html~
|-- server.py
`-- www
    |-- item_apps.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  カメラ OV5647 HDカメラモジュール
HiLetgo OV5647 5MP Raspberry Pi カメラ OV5647 HDカメラモジュール
Amazon

ネットワークカメラが人気!

【2020バージョンアップ400万画素】COOAU ネットワークカメラ ペット老人見守りカメラ
【2020バージョンアップ400万画素】COOAU ネットワークカメラ ペット老人見守りカメラ
Amazon
Wansview ネットワークカメラ 1080P 200万画素 ベイビーモニター WiFi IPカメラ ワイヤレス屋内防犯カメラ
Wansview ネットワークカメラ 1080P 200万画素 ベイビーモニター WiFi IPカメラ ワイヤレス屋内防犯カメラ
Amazon

人気のラズパイ

Raspberry Pi 4 Model B 8GB 技適マーク入 正規品!ラズベリーパイ4 モデルB
Raspberry Pi 4 Model B 8GB 技適マーク入 正規品!ラズベリーパイ4 モデルB
Amazon
TRASKIT Raspberry Pi 4 Model B Starter Kit
TRASKIT Raspberry Pi 4 Model B Starter Kit
Amazon
Raspberry Pi Zero W - ヘッダー ハンダ付け済み
Raspberry Pi Zero W - ヘッダー ハンダ付け済み
Amazon

人気のラズパイ周辺機器

10 インチRaspberry Pi用タッチモニター EleDuino HDMI モバイルディスプレイ
10 インチRaspberry Pi用タッチモニター EleDuino HDMI モバイルディスプレイ
Amazon
Raspberry Pi4 Model B /アルミニウム金属ケース/ファンレス/放熱シート付き
Raspberry Pi4 Model B /アルミニウム金属ケース/ファンレス/放熱シート付き
Amazon
Freenove Raspberry Pi 4 B 3 B+ 400用の究極のスターターキット
Freenove Raspberry Pi 4 B 3 B+ 400用の究極のスターターキット
Amazon
KEYESTUDIO DC 5V 4チャンネル リレーシールドモジュール 拡張ボード for Raspberry Pi
KEYESTUDIO DC 5V 4チャンネル リレーシールドモジュール 拡張ボード for Raspberry Pi
Amazon

Raspberry Piのオススメ入門書

Raspberry Piクックブック 第3版 (Make:PROJECTS)
Raspberry Piクックブック 第3版 (Make:PROJECTS)
Amazon
これ1冊でできる! ラズベリー・パイ 超入門 改訂第6版 Raspberry Pi 4/Zero W対応
これ1冊でできる! ラズベリー・パイ 超入門 改訂第6版 Raspberry Pi 4/Zero W対応
KindleAmazon
写真や図解でよくわかる ラズパイZeroを使い倒す本 Raspberry Pi Zero W対応
写真や図解でよくわかる ラズパイZeroを使い倒す本 Raspberry Pi Zero W対応
KindleAmazon
記事に関するご質問などがあれば、ぜひTwitterへお返事ください。