ラズパイからRTMPでライブ配信(ニコ生)
この記事では、Raspberry Pi(以下ラズパイ)からニコニコ生放送(以下ニコ生)へRTMP配信する方法を解説します。ニコ生以外にも、RTMP配信に対応しているサイトなら同じ方法で配信が可能です。というかほとんどのライブ動画サイトはRTMPに対応してます。
Raspberry Pi 3B+と1000円程度のカメラモジュールでの配信なので画質は良くありませが、ご参考になれば幸いです。
つかうもの
はじめに、この記事でつかうものをご紹介します。
ラズパイ
手持ちの少し古いRaspberry Pi 3B+を使いましたが、できるだけ最新のRaspberry Piを使うのがおすすめです。
カメラ
1000円程度で購入できるカメラモジュールを使用しました。
また、ロジクールの安価なUSBカメラでも配信を試してみました。
ただし、USBカメラの場合は15fpsが限界でした。というのも、それ以上fpsを上げると音声にデジタルノイズが入ってしまうんです。一方、カメラモジュールだと30fpsでも問題ありませんでした。ここら辺は私の設定の問題だったのか分かりませんが、一応ご参考までに。
他にもズーム機能付だったり、赤外線で夜間も撮影できるカメラもあります。
ヒートシンク
動画など重い処理をRaspberry Piで行う場合、CPUが発熱して本体が壊れてしまう可能性があります。必ずヒートシンクや放熱性のあるケースに入れて熱対策をしましょう(私は放熱対策せず、過去にRaspberry Piを壊してしまったことがありますのでご注意ください)。
Raspberry Piでカメラ使う準備
Raspberry Piでカメラモジュールを使えるようにするには、こちらの記事に詳しく書きました。
また、USBカメラを使う場合とくに必要な設定はありません。Raspberry PiにUSBカメラを接続して $ lsusb コマンドを実行すると次のようにカメラが認識されているはずです。
$ lsusb
Bus 001 Device 004: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 005: ID 0424:7800 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ ls /dev/video*
/dev/video0 /dev/video1 /dev/video10 /dev/video11 /dev/video12
オーディオ入力のデバイスは次のコマンドで確認します。
$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: U0x46d0x825 [USB Device 0x46d:0x825], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: H5 [H5], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
ここではZOOM H5のUSBオーディオインターフェイスを接続しました。card 1 card 2 がサウンドカード番号です。音声を扱う際に必要となるので覚えておきます。
ffmpegをソースからコンパイル・インストール(ハードウェアエンコード)
RTMP配信を行う際に、動画を適切にエンコードするエンコーダーが必要になります。ここではffmpegを使用しました。
ただし、$ apt install ffmpegでインストールするffmpegは、ソフトウェアエンコード処理になりますので、CPU負荷が高いです。実際試してみると、CPU使用率が100%を超えます。ですから、ffmpegはソースコードをダウンロードして自分でコンパイルするのがおすすめです。そうすることで、ハードウェアエンコードで動画処理することが可能です。
すでにffmpegが入っている場合は $ apt remove ffmpeg で削除してしまいます。
そして、apt-getを最新の状態にしておきましょう。
$ sudo apt-get update
$ sudo apt-get upgrade
ハードウェアエンコードするには h264_omx というコーデックが必要でした。しかしffmpeg 4.x系だと h264_omx が非推奨です。仕方ないので少し古いffmpeg 3.4をダウンロードしインストールすることにしました。
$ git clone git://source.ffmpeg.org/ffmpeg ffmpeg/release/3.4.8 --depth=1
ffmpegをコンパイルする前に、alsaというサウンド周りのライブラリを入れておきます。 alsaの公式ホームページ から最新版のalsa-libをダウンロードしてコンパイルします。
$ wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.2.4.tar.bz2
$ tar xjvf alsa-lib-1.2.4.tar.bz2
$ cd alsa-lib-1.2.4
$ ./configure --prefix=/home/pi/ffmpeg/release/3.4.8
$ make
$ make install
以上を実行すると ./ffmpeg/release/3.4.8 の中にlibディレクトリ作られalsa-lib 関係のライブラリが入っているはず。
必要かどうか分かりませんが次のライブラリも入れておきました(ffplayのビルド用?)。
$ sudo apt-get install libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev
こちらも(OMX_Core関係?)。
$ sudo apt-get install libomxil-bellagio-dev -y
以上、ここからいよいよffmpegをコンパイルします。ソースディレクトリへ移動しましょう。
$ cd ./ffmpeg/release/3.4.8
次のように、必要なライブラリを指定します。
./configure --enable-gpl --enable-nonfree --enable-mmal --enable-omx-rpi --enable-omx --extra-cflags="-I/home/pi/ffmpeg/release/3.4.8/include" --extra-ldflags="-L/home/pi/ffmpeg/release/3.4.8/lib" --extra-libs=-ldl
Raspberry Pi 3B+のCPUはクアッドコアとのことで、以下のように4スレッドでコンパイルすると多少時間が早まるようです。それでも30分くらいコンパイルに時間がかかりましたが。
$ make -j4
$ sudo make install
以上でffmpegのインストール完了です。 $ which ffmpeg でインストールされた場所を確認できるはずです。
ラズパイからffmpegでRTMP配信
それではラズパイからffmpegでニコ生へRTMP配信を行なってみましょう。ニコ生のRTMPエンドポイントは、URLとストリームキーをスラッシュ/で繋げたものになります。 ▼ ニコ生のRTMPについてはこちら。
さて、ここからはffmpegのオプションを試行錯誤してなんとか配信できたコマンドをご紹介いたします。ffmpegではオプションの順番も重要になってきます。画像サイズとかは改良の余地がありそうです。
カメラモジュールからの配信コマンド
$ ffmpeg \
-f alsa -ac 2 -thread_queue_size 16384 -i hw:1 \
-f v4l2 -thread_queue_size 16384 -video_size 640x480 -framerate 30 -i /dev/video0 \
-c:v h264_omx -b:v 768k -bufsize 768k -vsync 2 -g 16 \
-c:a aac -b:a 192k -ar 48000 \
-f flv rtmp://tliveorigin.dmc.nico/named_input/ストリームキー
USBカメラからの配信コマンド
$ ffmpeg \
-f alsa -ac 1 -thread_queue_size 8192 -i hw:1 \
-i /dev/video0 \
-c:a aac -b:a 128k -ar 44100 \
-f flv rtmp://tliveorigin.dmc.nico/named_input/ストリームキー
$ ffmpeg -threads 2 \
-f alsa -ac 2 -thread_queue_size 8192 -i hw:2 \
-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 2 -g 16 \
-c:a aac -b:a 192k -ar 48000 \
-f flv rtmp://tliveorigin.dmc.nico/named_input/ストリームキー
$ ffmpeg \
-f alsa -ac 2 -thread_queue_size 16384 -i hw:1 \
-f h264 -thread_queue_size 16384 -video_size 640x480 -framerate 30 -i /dev/video0 \
-c:v h264_omx -b:v 768k -bufsize 768k -vsync 2 -g 16 \
-c:a aac -b:a 192k -ar 48000 \
-f flv rtmp://tliveorigin.dmc.nico/named_input/ストリームキー
これらのコマンドでRTMP配信できるか試してみてください。はじめにお伝えしたとおり、映像のキレイさはラズパイやカメラのスペックに依存しますので、ライブ配信ですとできるだけ高スペックなマシンが要求されます。
2022年の最新情報としまして、ライブ配信界隈ではSRT + H.265による配信が最先端なようです。自宅に中継サーバーを立てて、SRT→RTMP、H.265→H.264へ変換してライブ配信する感じです。私も試したことはあるのですが、中継サーバーがRaspberry Pi 3B+だと変換処理が間に合わずダメでした。みなさんに話を聞くと、Jetson Nanoを使ってやられているようです。ここら辺はまた別の機会があれば記事にします。
ffpmegのオプション
RTMP配信で使ったffpmegのオプションの意味は次のとおりです。
オプション | 意味 |
---|---|
-i hw:1 | サウンドカードの番号を指定 |
-ac | 音声のチャンネル数(モノ:1、ステレオ:2) |
-ar | 音声のサンプリング周波数 |
-b:a | 音声のビットレート |
-vsync | 1で固定フレームレート 2で可変フレームレート |
-framerate | 映像のFPS |
-c:v | 映像のコーデック(h264_omxでハードウェアエンコードになる) |
-b:v | 映像のビットレート |
-c:a | 音声のコーデック(ニコ生の場合aacを指定) |
Raspberry Piでソフト的な手振れ補正ができればと思ったのですが、リアルタイムで出来そうなものは見つかりませんでした。リアルタイム処理でなければ、Video Stabilization(vid.stab)が使えるようです。
▼ こちらはPythonライブラリのVidStabを使った記事です。
カメラの性能を調べる便利なコマンド
本題とはそれますが、最後にカメラの性能を調べられる便利なコマンドを紹介します。
次は、ffmpegで利用可能なコーデックを一覧表示する例です:
$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
...
[video4linux2,v4l2 @ 0x2212220] Raw : yuv420p : Planar YUV 4:2:0 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x2212220] Raw : yuyv422 : YUYV 4:2:2 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x2212220] Raw : rgb24 : 24-bit RGB 8-8-8 : {32-2592, 2}x{32-1944, 2}
[video4linux2,v4l2 @ 0x2212220] Compressed: mjpeg : JFIF JPEG : {32-2592, 2}x{32-1944, 2}
...
接続するカメラによっては次のように表示されます。
$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
...
[video4linux2,v4l2 @ 0x2ab4220] Raw : yuyv422 : YUYV 4:2:2 : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
[video4linux2,v4l2 @ 0x2ab4220] Compressed: mjpeg : Motion-JPEG : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
次は、接続されているカメラのコーデックや画像サイズ、FPSなどを確認できる例です:
$ v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Index : 1
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
pi0 23:10 ~ $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
...
次は、カメラのfpsをテスト実測する例です:
$ v4l2-ctl --stream-mmap=3 --stream-count=300
<<<<<<<<<<<<<<<< 15.00 fps
<<<<<<<<<<<<<<< 14.92 fps
<<<<<<<<<<<<<<< 14.90 fps
<<<<<<<<<<<<<<< 14.88 fps
<<<<<<<<<<<<<<< 14.91 fps
<<<<<<<<<<<<<<< 14.90 fps
<<<<<<<<<<<<<<< 14.89 fps
次は、カメラの画質を設定変更してからfpsを計測している例です:
$ v4l2-ctl --set-fmt-video=width=640,height=480,pixelformat=1
$ v4l2-ctl --stream-mmap=3 --stream-count=300
<<<<<<<<<<<<<<<<<<<<<<<<<< 24.27 fps
<<<<<<<<<<<<<<<<<<<<<<<< 24.13 fps
<<<<<<<<<<<<<<<<<<<<<<<< 24.09 fps
<<<<<<<<<<<<<<<<<^C
$ v4l2-ctl --set-fmt-video=width=640,height=480,pixelformat=0
$ v4l2-ctl --stream-mmap=3 --stream-count=300
<<<<<<<<<<<<<<<<< 15.09 fps
<<<<<<<<<<<<<<< 15.12 fps