2023/08/03(木)64bit Raspberry Pi OSでターミナル動画再生サイネージ

「ラズパイでデジタルサイネージ的なもの作れない?」と依頼されたので構築したときのメモ。Xを入れずにコンソール(CUI)のみで作りましたが、結構手間取りました……。

※omxplayerは開発終了(deprecated)しているので使用しません。

概要

  • Raspberry Pi OS 64bit Lite版(bullseye)
    • GUI/Desktop(X Window System)不使用。
  • WiFi接続。
  • 起動後自動的に動画を再生する(rtspでもファイルでも)。

初期設定

  1. イメージを普通にSDに焼き込む。
  2. 解像度を1280x720にしたいので、config.txtを修正。HDMI設定の詳細は公式参照。
    # Resolution on boot
    framebuffer_width=1280
    framebuffer_height=720
    
    # 1280x720 60Hz mode
    hdmi_group=2
    hdmi_mode=85
    
    # Enable audio
    hdmi_drive=2
    
  3. 普通に起動して初期設定。
  4. raspi-config起動
    • System Options→Hostnameを適時
    • Display Options→Screen Blanking→Disable
    • Interface Options→SSH→Enable
    • Localisation Options
      • Timezone→Asia/Tokyo
      • Keyboard→Japanese
      • WLAN Country→JA ※必須。設定しないとWiFiが使用できない。
  5. /etc/wpa_supplicant/wpa_supplicant.confを編集
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    country=JP
    
    network={
            ssid="SSID"
            psk="PASSWORD"
    }
    
  6. 音を問題なく鳴らすため、/etc/asound.conf を作成する(情報元)。
    # /etc/asound.conf
    defaults.pcm.card 1
    defaults.ctl.card 1
    
    • 再生テスト: speaker-test
    • うまくならないときは、~/.asoundrc を削除。

補足

本来なら「fbset -g 1280 720 1280 720 16」で画面解像度が設定できるのですが、config.txtで

dtoverlay=vc4-kms-v3d

を使用すると(ラズパイの標準で有効)、起動時にこのモジュールを初期化した段階で(hdmi_modeを指定してなければ)解像度が1980x1080等に固定されてしまい、fbsetしても1980x1080内の描画領域を選択するだけという無惨なことになります。

dtoverlay=vc4-kms-v3dをコメントアウトすると、fbsetまわりが正しく動作するようになりますが、KMS/DRMという新しい形式のAPIは動作しなくなります。

Desktop環境を使用しない(ターミナルで使用する)場合、vc4-kms-v3dモジュールを組み込まない方が運用が楽なのですが、後述するとおりKMS/DRM APIを使用したいので組み込んだままにしておきます。

動画の再生設定

ネット上の作例は、大半がomxplayerを使用したもので、一部ffmpegを使用したものも見受けられますが、以下の理由からどちらも採用しませんでした。

  • 64bit環境では omxplayer は使用できない。*1
  • ffmpegはとある問題で実用にならなかった。

VLCによる再生

VLCはDesktop環境では初めから入っているようですが、VLC自体はコンソールでも動作します(AsciiArtで動画を再生することもできるくらいです)。

apt install vlc

再生自体簡単で、

vlc --loop --vout=drm_vout PLAY_FILE

とすればokです。ここでは「ループ再生」と「KMS/DRMを使用しての描画」をオプション指定しています。(SSH等ではなく)HDMI画面表示されているターミナルから直接入力すれば、--voutを付けなくても色々な描写手段を試して自動的に適切な方法で表示してくれます。

起動時に自動的に再生させるために、autoplay.shというスクリプトをユーザーのホームに用意しました。

#!/bin/sh

# ファイル再生の場合
exec vlc --loop --no-video-title-show --vout=drm_vout PLAY_FILE

# RTSP/TCP再生の場合
exec vlc --loop --no-video-title-show --vout=drm_vout --rtsp-tcp rtsp://RTSP_URL

自動起動の設定は corntab -e に設定。

# m h  dom mon dow   command
@reboot              ./autoplay.sh   1>/dev/null 2>&1

VLC on Framebufferは断念

vlcにはKMS/DRM以外にも、(vc4-kms-v3dを組み込んでない)従来のフレームバッファー(/dev/fb0)へ描画するモードもあります。

vlc --vout=fb --fbdev=/dev/fb0 PLAY_FILE

とすれば良いことになっていますが、実際は、HDMI表示されたターミナルから直接起動しないと描画できない(方法がないor分からない)ので断念しました。*2

ffmpegを使用した方法の問題

ffmpegにはフレームバッファに動画を出力する機能があります。

# 32bit color
ffmpeg -i file -s 1280x720 -pix_fmt bgra888 -f fbdev /dev/fb0
# 16bit color
ffmpeg -i file -s 1280x720 -pix_fmt rgb565 -f fbdev /dev/fb0

しかしCPU負荷が高くて全く描画が追いつきません。ハードウェアコーデック(h264_v4l2m2m)を使用したり色々と試してみたのですが、/dev/nullとかに出力すると負荷的に全く問題ない。

ffmpeg -i file -s 1280x720 -pix_fmt bgra888 -f rawvideo /dev/null

どうやらffmpegのフレームバッファ書き込みが致命的に遅いようで、これはどうやっても解決不能なので諦めました。

*1 : 32bit Bullseye環境で一応試したものの、一部表示化けしたことと、OS全体の処理が明らかに64bit環境より遅いのでやめた。

*2 : 自動ログインと組み合わせれば問題なさそうではあるけどもそこまでしたくない。

SDの保護

全部設定が終わったら、運用によってはOverlay File Systemをonにしたほうが良いでしょう。

まとめ

omxplayerは廃れることが約束されているので、ラズパイで動画再生するならVLCを使用しましょう。