FFmpeg を使って YouTube Live にカメラ配信する方法(Raspberry Pi)

Linux,お役立ち情報,プログラムbash,ffmpeg,Raspberry Pi,YouTube

Raspberry Pi (Linux) を使って FFmpeg で YouTube Live を配信する方法についてまとめておきます。下に示すのは実際にライブ配信した例です(配信が停止して URL が変わっているかもしれません。その場合は私の YouTube チャンネルに行けば配信状況を確認できます。)。

配信アーカイブ例

これはタイムラプスにした例です。

配信例(配信内容のタイムラプス)

毎日アーカイブしています。こちらの作り方は記事「Raspberry Pi でタイムラプス動画を撮り YouTube に自動アップロードする」をご覧ください。

USB カメラの映像を配信する

とりあえず Raspberry PI に USB カメラをつないで以下のコマンドを実行すれば、上で紹介したようなライブ配信ができます。これは左上に日付時間表示をカメラ映像にオーバレイして、任意の音声を無限ループでストリーミングする設定です。

stream_key="XXXX-XXXX-XXXX-XXXX-XXXX" # ストリームキーを記述
audio_file="path/to/audio/file.mp3" # BGM 用の音声ファイルへのパスを記述

ffmpeg -re -stream_loop -1 -i "${audio_file}" \
    -f v4l2 -input_format mjpeg -framerate 30 -video_size 1920x1080 -i /dev/video0 \
    -vcodec libx264 -preset veryfast -tune zerolatency -pix_fmt yuv420p \
    -vf "drawtext=fontfile=/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf:x=2:y=2:fontsize=32:fontcolor=white:box=1:boxcolor=black@0.4:text='%{localtime} Sapporo Sta.'" \
    -b:v 4500k -maxrate 4500k -bufsize 9000k -g 60 -r 30 \
    -acodec aac -ar 44100 -b:a 128k -f flv \
    rtmp://a.rtmp.youtube.com/live2/${stream_key}

「stream_key」のところに YouTube Live の配信キーを設定します。「audio_file」に任意の音声ファイルへのパス、drawtext の fontfile にはシステムに入っているフォントファイルを指定します<ref>Raspberry Pi の Raspberry Pi OS の場合はこのパスで Noto フォントが使える</ref>。これは右上に表示する文字列のフォントになります。

-i オプションで指定するカメラデバイスは v4l2-ctl コマンドで確認できます。

$ v4l2-ctl --list-devices # インストールするときは sudo apt install v4l-utils
...
USB 2.0 Camera: USB Camera (usb-0000:01:00.0-1.4):
	/dev/video0
	/dev/video1
	/dev/media4

接続されているカメラがいくつか出てきますが、今回の場合は /dev/video0 が該当するカメラデバイスのようです。fswebcam コマンドを使って画像を撮ってみると確認できるでしょう。

# USB カメラで撮影テスト みつからなければ sudo apt install fswe
fswebcam -d /dev/video0 -r 1280x768 cam_test.jpg

配信可能な解像度やフレームレートも同じく v4l2-ctl コマンドで取得できます。

$ v4l2-ctl --list-formats-ext -d /dev/video0

ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'MJPG' (Motion-JPEG, compressed)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.033s (30.000 fps)
        ##### 省略 #####
        [1]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.100s (10.000 fps)
        ##### 省略 #####

このリストから YUYV フォーマットではフル HD の 1920×1080 だと 5.0 fps でしか出力できないこと、MJPG フォーマットであればフル HD で 30.0 fps で出力できることがわかります。この情報から

# MJPG の場合の例
-input_format mjpeg -framerate 30 -video_size 1920x1080
# YUYV の場合の例
-input_format yuyv422 -framerate 10 -video_size 1280x960

などと指定します。

配信には音声も必須

配信動画に音声チャンネルが存在しないと YouTube Live は配信できないようなので、無音でもいいので音声ファイルをくっつける必要があります。

とりあえず 5 秒間の無音 mp3 ファイルを上げておくので、必要があればダウンロードしてください。

無音の 5 秒間音声

なおこの音声はオープンソースの音声処理プログラムの SoX (Sound eXchange) を使って作成しました。wave ファイル作成後、ffmpeg で mp3 に変換しています。

sox -n -r 44100 -b 16 -c 1 -e signed-integer no_sound.wav trim 0.0 5.0
ffmpeg -i no_sound.wav -vn -ac 2 -ar 44100 -ab 256k -acodec libmp3lame -f mp3 no_sound.mp3

カメラのマイクを使って音声を取得する

USB カメラのマイクからの音声を使うには以下のようにします。

ffmpeg -re -f alsa -thread_queue_size 8192 -i hw:2,0 \ # 最初のところだけ差し替え
  -f v4l2 -input_format mjpeg -framerate 30 # ... 以下同じ 

-i hw:2,0 に与えるハードウェアデバイス番号を得るには arecode コマンドを使います。

arecord -l                                                                                                                                                                                                     [2022/03/09 16:57:40]
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: Camera [USB 2.0 Camera], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

この出力結果の「カード 2」と「デバイス 0」をそれぞれ hw:2,0 のように指定します。

今回の例ではマイクデバイスが 1 つしかありませんが、状況に応じて適切なデバイスを指定します。

配信をし続けるためにループさせる

Raspberry Pi で配信し続けると、どうも高負荷になって ffmepg が落ちてしまうことがあるようです。YouTube Live は配信停止が短時間であれば再配信できるので、無限ループで実行して配信し続けられるようにしてみました。

#!/bin/sh

stream_key="ストリームキー"
audio_file="音楽.mp3"

while true
do
  ffmpeg -re -stream_loop -1 -i "${audio_file}" \
    -f v4l2 -input_format mjpeg -framerate 30 -video_size 1920x1080 -i /dev/video0 \
    -vcodec libx264 -preset veryfast -tune zerolatency -pix_fmt yuv420p \
    -vf "drawtext=fontfile=/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf:x=2:y=2:fontsize=32:fontcolor=white:box=1:boxcolor=black@0.4:text='%{localtime} Sapporo Sta.'" \
    -b:v 4500k -maxrate 4500k -bufsize 9000k -g 60 -r 30 \
    -acodec aac -ar 44100 -b:a 128k -f flv \
    rtmp://a.rtmp.youtube.com/live2/${stream_key}
done

このスクリプトを実行すれば、途中で ffmpeg が落ちてもすぐに配信が再開できます。例えば tmux のようなターミナルマルチプレクサで実行しておけばそれなりに長く配信できます。

また /etc/rc.local にこのシェルスクリプトの実行を指定しておけば、電源がついて準備出来次第、自動で配信を開始することができます。

/bin/bash /home/USER/loop_stream.sh

カメラではなく保存した動画を配信する方法

カメラから取得した映像ではなく、保存してある動画や静止画 + 音声を配信する方法は記事「FFmpeg で動画や静止画 + 音声を YouTube Live 配信する」 をご覧ください。

上記で紹介したように記事「Raspberry Pi でタイムラプス動画を撮り YouTube に自動アップロードする」にはタイムラプス動画を作成し、自動でアップロードする方法を解説しています。

参考資料