動かざることバグの如し

近づきたいよ 君の理想に

Raspberry PiをBluetoothスピーカーにして音楽を鳴らしたい人生ができた(完成版

やりたいこと

スマホとRaspberry PiをBluetoothでペアリングし、スマホから流した音楽をRaspiを通してスピーカーで聴く

f:id:thr3a:20150903171844p:plain

用意するもの

  • Raspberry Pi2(2015-05-05-raspbian-wheezy、jessie不可!)
    • raspi-configにてイヤホンジャックから音が出るように&グラフィックモード(起動時startx)にしておく
  • スピーカー
  • Bluetooth対応スマホ

手順

インストール

sudo apt-get install bluez bluez-tools pulseaudio-module-bluetooth python-gobject python-gobject-2

PulseAudio設定

Bluetoothで受信した音声をオーディオ出力に受け渡すのにPulseAudioというアプリケーションを使う

Bluetoothデーモンにアクセスできるようにlpグループにpiを追加

sudo usermod -a -G lp pi

/etc/pulse/daemon.confより、以下を追記

resample-method = trivial
exit-idle-time = -1
  • trivialが一番低負荷とのこと。こちらのサイトに一覧載ってるけど負荷と音質がトレードオフの模様。
  • exit-idle-time = -1を指定してあげないとデフォルトだと20秒後に待機モードに入って音楽が止まってしまう

Bluetooth設定

/etc/bluetooth/audio.confより、[General]項目に以下を追加

[General]
Enable=Source,Sink,Gateway,Control,Socket,Media

次に音の出力先名を確認するために以下のコマンド実行

sudo -u pi pactl list short sinks

下記のようなリストが出てきたらこれを控えておく。例だとalsa_output.0.analog-stereoが名前になる

pi@raspberrypi ~ $ sudo -u pi pactl list short sinks
0       alsa_output.0.analog-stereo     module-alsa-card.c      s16le 2ch 44100Hz       SUSPENDED

Bluetoothが接続された時に自動的にPulseAudioと連携して音声が出力できるように設定する。適当に/home/pi/speaker.shを作成。 実行権限を与えておく(0755)

#!/bin/bash

AUDIOSINK="alsa_output.0.analog-stereo"

echo "Executing bluetooth script...|$ACTION|" >> /var/log/bluetooth_dev

ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")
if [ "$ACTION" = "add" ]; then
   for dev in $(find /sys/devices/virtual/input/ -name input*); do
      if [ -f "$dev/name" ]; then
         mac=$(cat "$dev/name" | sed 's/:/_/g')
         bluez_dev=bluez_source.$mac

         sleep 1

         CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`
         if [ ! -z "$CONFIRM" ]; then
            echo "Setting bluez_source to:  $bluez_dev" >> /var/log/bluetooth_dev
            echo pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
            sudo -u pi pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
         fi
      fi
   done
fi

if [ "$ACTION" = "remove" ]; then
   CONFIRM=`sudo -u pi pactl list short | grep 'module-loopback\ssource=bluez_source'`
   if [ ! -z "$CONFIRM" ]; then
      module_id=`echo $CONFIRM | sed 's/\s.*//'`
      echo pactl unload-module $module_id >> /var/log/bluetooth_dev
      sudo -u pi pactl unload-module $module_id >> /var/log/bluetooth_dev
   fi
fi

Bluetoohのペアリング完了後に発火させたいので/etc/udev/rules.d/99-input.rulesに以下追記

KERNEL=="input[0-9]*", RUN+="/home/pi/speaker.sh"

最後に/etc/rc.localに以下を追記

start-stop-daemon -S -x /usr/bin/bluetooth-agent -b -- 0000
# ↓たぶん勝手に実行されてるはず
# pulseaudio --log-target=syslog -D
hciconfig hci0 piscan

これで再起動すればおk

強制ペアリング有効

sudo hciconfig hci0 piscan