サウンドデバイスを接続したRaspberry Piでmpdを動かしてPC等から再生

Last modified: 2021-11-03

記事概要と要件

Raspberry Pi製品には高音質なI2S接続サウンドカードやUSB DACを付けて音楽鑑賞をする用途があり、OS(ディストリビューション)の形で配布されているソフトウェアもあるが、Raspberry Pi OSを動かしている場合であっても音楽再生ソフトを使えば実現できる。

本記事では音楽再生用途のサウンドデーモン “Music Player Daemon (MPD)” を用いる形でPC上の音楽ファイルなどを再生してRaspberry Pi側のサウンドデバイスから出力するための環境についてを扱う。

ハードウェア要件

  • Raspberry Pi製品 (サウンドデバイスが接続されているもの)
    • GPIO接続サウンドカードやUSB DACなどが接続されている
    • 画面出力やキーボード・マウスなどはSSHやVLCによる遠隔操作が可能なところまで設定されていれば不要
  • デスクトップ用途のPCやRaspberry Pi(4系以上推奨)など
    • サウンドデバイスの接続されたRaspberry Pi製品とLAN(イーサネットガジェットとして動作させたときのUSB接続含む)で接続されている
    • 音楽データはこちら側に接続されたストレージに含まれる

手元の環境ではPi Zeroをイーサネットガジェットとして動かして接続している。

ソフトウェア要件

  • Raspberry Pi製品 (サウンドデバイスが接続されているもの)
    • OSはRaspberry Pi OS
      • I2Sサウンドカード使用時は/boot/config.txtにおいてサウンドカードに合ったdtoverlay=などの記述の追加後に起動しておく
      • カーネルを自分でビルドしている場合、サウンドカードに合ったサウンドドライバが有効になっている必要がある
    • MPDおよびその依存ライブラリ群
      • Raspberry Pi OSのパッケージをインストールする場合は依存パッケージは自動的にインストールされる
  • デスクトップ用途のPCやRaspberry Pi
    • OSはLinux(Raspberry Pi OSを含む)など
    • MPD (データベースプロキシ用途)
      • PC上の音楽ファイルを再生する場合には強く推奨
      • ディストリのパッケージでもよい
    • SMBサーバ(SambaまたはWindowsの共有)またはNFSサーバ
      • ここではこれらの設定については扱わない

IPアドレスについては、どちらも固定されていることを前提とする。

リモートマシンにある音楽データの再生のために必要なもの

音楽データのあるマシンはPiから見るとリモートマシンとなるため、MPDにおけるSMB(libsmbclient)またはNFS(libnfs)のクライアント機能を有効にする必要がある。

これはLinuxカーネルのファイルシステムサポートとは異なる。カーネルの機能でマウントしたリモートマシン上の場所にある音楽ファイルを再生すると音が途切れることがあるため、ユーザ空間のライブラリを用いて処理を行う必要がある。

Raspberry Pi OSを含むディストリのパッケージのMPDではSMBやNFSの機能は有効になっていることが多い。

libsmbclientを用いる場合、データベースの更新時や更新後の再生開始のタイミングでMPDが落ちることがある。安定した動作が重要であればNFSを用いたほうがいいかもしれない。

データベース更新にかかるコストを抑えるための構成

MPDを普通のやり方で設定すると、Pi側にデータベースが作成されて管理される。

この場合、データベースを更新すると音楽データのあるPCなどの側から音楽ファイルを片っ端から転送する上、低速なPiのCPUで読み込むことにもなり、非常に時間がかかる上にネットワーク帯域も浪費してしまうという問題がある。

そこで、PCなどの側でもう一つMPDを動かすようにしてデータベースの設定を適切に行うと、データベース更新をPCなどの側にあるMPDに依頼して新しくできたデータベースだけを受け取るようにする構成(Satellite setup)にすることができ、データベース更新にかかる時間とネットワーク帯域の使用を大幅に削減できる。

この機能にはlibmpdclientライブラリとMPD自体の同ライブラリのサポートが必要。これもRaspberry Pi OSを含むディストリのパッケージのMPDでは有効になっていることが多い。

MPDの設定ファイル内の項目

音楽のディレクトリとデータベース

音楽ディレクトリ

リモートマシン上の音楽ディレクトリとして

  • SMB: smb://
  • NFS: nfs://

のURLで記述し、対応する入力プラグインについての記述も追加する。

[一部]ファイル名:mpd.conf(Pi側)
# SMBの場合
music_directory         "smb://user:password@ipaddress/sharename/path"
input {
	plugin "smbclient"
}

# NFSの場合
music_directory         "nfs://ipaddress/path"
input {
	plugin "nfs"
}

上の例で強調されている行の値は、環境に合わせたものにする。

データベース

既定の設定ファイルではdb_fileという項目でローカルのデータベースファイルの場所を定義するのだが、ここではPi側において以下の編集を行う。

  • db_fileの記述は削除またはコメントアウト
  • databaseセクションでproxyプラグインを設定
    • PCなどのIPアドレス(host),そこで動作しているMPDのポート番号(port)とパスワード(password)を環境に合わせて設定
[追記][一部]ファイル名:mpd.conf(Pi側)
database {
       plugin "proxy"
       host "ipaddress"
       port "6600"
       password "mypassword"
}

音楽ファイルのあるPCなどの側では、music_directoryでPi側から共有されている最上位のディレクトリを指定した上で、db_fileを記述する形でローカルにデータベースを配置しておく。

[一部]ファイル名:mpd.conf(PCなどの側)
# SMBやNFSで共有される最上位の音楽ディレクトリを指定
# Pi側の設定ファイルで指し示されている階層に対応するようにする
music_directory		"/path/to/shared_music_directory"

# ローカルのストレージにデータベースファイルを配置
db_file			    "/path/to/mpd/tag_cache"

また、PCなどの側がLinuxの場合、以下の設定の記述を行うと、Linuxカーネルの “inotify” の仕組みを用いて、音楽ディレクトリ内に変更があった際にカーネルから通知を受け取って自動的にデータベースの更新を行うことが可能。

[一部]ファイル名:mpd.conf(PCなどの側)
# 以下の設定項目は初期状態の設定ファイルではコメントアウトされた形で入っている

# 音楽ディレクトリ内が変更されたら自動的にデータベースを更新
auto_update         "yes"
# 監視するディレクトリの深さの制限を必要に応じて指定
auto_update_depth   "3"

この機能はディストリのパッケージになっているMPDを使用していれば有効になっていることが多い。

サウンドデバイスの設定

音声の出力先デバイスを指定したり、MPDクライアント(Cantataなど)からの音量調整が正しく動作するように記述を行う。

手元の環境(JustBoom DAC Zero)では、ALSAのドライバにおける情報は

[Raspberry Pi]# cat /proc/asound/cards
 0 [sndrpijustboomd]: JustBoomDac - snd_rpi_justboom_dac
                      snd_rpi_justboom_dac

となっており、音量調整についてはalsamixerを使ったときに主にDigitalというミキサー項目で調整する形1なので

[一部]ファイル名:mpd.conf(Pi側)
audio_output {
    type           "alsa"
    name           "snd_rpi_justboom_dac"
    device         "hw:sndrpijustboomd"
    mixer_control  "Digital"
}

という設定を記述して、音量調整も含めて正しく動作している。

上の例を参考にする場合、得られた情報のどの部分が設定ファイルのどの部分に対応しているかを見て設定値を決めるとよい。

MPDはJACKを用いることもできるのだが、JACKを用いる設定にすると、ALSAのミキサー項目がいじれないため音量調整機能が動かない。
手元の環境では、netjack2を使用したいときだけMPDクライアントを終了後にJACKを起動し、MPDを使うときになったらkillall jackdでJACKを終了させている。

残りの準備

MPDデーモンについては、前述のデータベースのプロキシ機能を用いる場合は音楽ファイルのあるPCなどの側で先に起動しておく必要がある。

その後でPi側のMPDを起動して、PCなどの側にある好みのMPDクライアント(Cantataなど)を設定する。

設定項目
ホスト(MPDサーバ) PiのIPアドレス
ポート Piの側で動作しているMPDのポート番号
パスワード Piの側で動作しているMPDのパスワード

これでデータベースの更新を行えばプレーヤとしての環境は出来上がりで、自動データベース更新を有効にしていれば、その後の音楽ディレクトリへの変更が自動で反映される。

initrdのみで動く最小限構成のシステムにおけるMPD

手元の環境では、update-initramfsで作成されたinitrdのみで動く最小限構成のシステムをPi Zero WHで動かしている。

ここでは、その中でMPDを使用する上のメモを扱う。

以下、この関連記事で扱っている “initrdのみの環境” についての内容を前提とする。

ユーザとグループ、アクセス権など

MPDの設定ファイル内のコメントによると、MPDはrootではなく一般ユーザの権限で動かすべきとされている。一方で、オーディオデバイスを扱えるようになっている必要もある。

/dev/snd/以下のオーディオデバイスファイルは初期状態では所有者rootしか書き込めないため

  • 新しいグループaudioを作成
  • そのグループのメンバとしてMPD用のユーザmpd2を追加
  • audioのメンバ全員がオーディオデバイスファイルに書き込めるようにアクセス権を設定

の3つを実行する。

また、サウンド関係のプログラムの動作には/usr/share/alsa/alsa.confが必要で、このファイルが一般ユーザから読み込めるようにアクセス権を修正する必要もある。

initrdのシステムが起動した後、MPDを動かす環境の準備として実行する ライセンス:CC0
#! /bin/sh

# ユーザとグループの準備
echo "audio:x:333:mpd" >> "/etc/group"
echo "mpd:x:222:333::/nonexistent:/usr/sbin/nologin" >> "/etc/passwd"

# アクセス権の修正
chmod go+rx /usr /usr/share /usr/share/alsa /usr/share/alsa/*
chmod g+rw /dev/snd/*
chown root:audio /dev/snd/*

alsa.confについては、initramfs-toolsのhooksのスクリプトにてcopy_file()またはcopy_exec()を用いてinitrdの作成時に含めるようにできる。

[追記][任意]ファイル名:/etc/initramfs-tools/hooks/custom
# Raspberry Pi OSのalsa.confをコピー
copy_file config /usr/share/alsa/alsa.conf

# 自分でビルドしたMPD(strip済み)を含める
copy_exec /usr/local/bin/mpd

これとは別にmpd.confも必要となるが、その中には平文のパスワードも含まれるため、Raspberry Pi OSのchroot環境に配置してhooksのスクリプトで中に含めるようにする場合は扱いに注意が必要。

MPDの手動ビルド設定例

USBデバイスブートでinitrdのみで動くシステムを動かす際には、initrdの圧縮後のサイズに制約があってOSの容量に余裕がないため、自分の用途で必要ないものはなるべく無効にして手動でビルドしている。

下はそのビルド設定を自動化した例。

[任意]ファイル名:configure-mpd.sh
# 初代PiやZero系の場合はarmv6向けの指定だが
# 新しいモデルではより新しい世代用の指定で高速化できる
CFLAGS="-march=armv6 -mfpu=vfp -mfloat-abi=hard -O2" \
CXXFLAGS="-march=armv6 -mfpu=vfp -mfloat-abi=hard -O2" \
meson _build \
    -Ddocumentation=disabled \
    -Dtest=false \
    -Dsyslog=disabled \
    -Dinotify=false \
    -Dsystemd=disabled \
    -Dipv6=disabled \
    -Ddsd=false \
    -Dupnp=disabled \
    -Dlibmpdclient=enabled \
    -Dneighbor=false \
    -Dudisks=disabled \
    -Dwebdav=disabled \
    -Dcdio_paranoia=disabled \
    -Dcurl=enabled \
    -Dmms=disabled \
    -Dnfs=disabled \
    -Dsmbclient=enabled \
    -Dqobuz=disabled \
    -Dsoundcloud=disabled \
    -Dtidal=disabled \
    -Dbzip2=disabled \
    -Diso9660=disabled \
    -Dzzip=enabled \
    -Did3tag=enabled \
    -Dchromaprint=disabled \
    -Dadplug=disabled \
    -Daudiofile=disabled \
    -Dfaad=disabled \
    -Dffmpeg=enabled \
    -Dflac=enabled \
    -Dfluidsynth=disabled \
    -Dgme=disabled \
    -Dmad=disabled \
    -Dmikmod=disabled \
    -Dmpcdec=disabled \
    -Dmpg123=disabled \
    -Dopus=enabled \
    -Dsidplay=disabled \
    -Dsndfile=disabled \
    -Dtremor=disabled \
    -Dvorbis=enabled \
    -Dwavpack=disabled \
    -Dwildmidi=disabled \
    -Dvorbisenc=disabled \
    -Dlame=disabled \
    -Dtwolame=disabled \
    -Dshine=disabled \
    -Dwave_encoder=false \
    -Dlibsamplerate=enabled \
    -Dsoxr=disabled \
    -Dalsa=enabled \
    -Dao=disabled \
    -Dfifo=false \
    -Dhttpd=false \
    -Djack=enabled \
    -Dopenal=disabled \
    -Doss=disabled \
    -Dpipe=false \
    -Dpulse=disabled \
    -Drecorder=false \
    -Dshout=disabled \
    -Dsndio=disabled \
    -Ddbus=enabled \
    -Dexpat=enabled \
    -Dicu=enabled \
    -Diconv=enabled \
    -Dpcre=disabled \
    -Dsqlite=disabled \
    -Dyajl=disabled \
    -Dzlib=enabled \
    -Dzeroconf=disabled
ビルド作業例
[mpd-x.y.z]$ /path/to/configure-mpd.sh
[mpd-x.y.z]$ meson compile -C _build
[mpd-x.y.z]# meson install -C _build

Pi側に音楽ファイルのストレージを接続する使い方では-Dinotify=falseの代わりに-Dinotify=trueを付けてデータベース自動更新機能が使えるようにしたほうがよい。


  1. AnalogueAnalogue Playback Boostという2段階の項目でも音量は変わり、特に前者で大きく上下するが、細かい調整はDigitalのみでできる ↩︎

  2. 既定の設定ファイルでユーザ名として記述されている名前 ↩︎