こんにちは、株式会社VALGOでテックリードを担っている村田と申します。
前回に続き、Raspberry Piを用いたIoT工作シリーズ第2弾です。
今回は、自宅から遥か数十Km先の事務所に置いてあるBluetoothスピーカーへ接続して音楽を流したい!という望みを叶えました。
ただし、数Kmどころか、数百m程度でも接続することは物理的に困難なため、Raspberry Piを使用することで擬似的に実現します。
Bluetoothの電波強度を上げて接続可能距離を広げてやろう…というような無茶はしません。(そんなことをしたら法に触れる恐れが…)
背景
私は普段、Bluetoothスピーカーを使って音楽を聴いています。
Bluetoothというのは距離が遠いとせいぜい10mくらいまでしか安定して接続できませんよね。
そこで私はふと思いました。
近距離という制限を無視してBluetoothスピーカーへ音楽を流す方法はないかなと。
思いつくものとしては、例えばスマートスピーカーAmazon Echoのマルチルームミュージックという機能があります。
これは、同じグループに属している(同じAmazonアカウントに紐づいている)全てのAmazon Echoへスマートフォンアプリから音楽を再生することができる機能です。
ただし、このような機能は一般的に全てのデバイスが同じWi-Fiネットワークに接続されていることが必須条件となっています。
私が実現したいのは、そのような条件の無いスピーカーです。つまり、インターネット環境さえあればどこからでも音楽を再生することができるということです。
手元に無いスピーカーへ音楽を流してどうするの?と思うかもしれませんが、自分もそう思っています。
これが実現したところで用途は特に考えていませんが、何となく面白そうだと感じたので、出来るだけ簡単に実現してみました。
ということで、今回は実現までの道のりについて記載していきたいと思います。
目的
遠距離にあるBluetoothスピーカーへBluetooth接続して音楽を流したい
要件
音楽を流したい端末からBluetooth接続で音楽再生ができること
これが最も重要であり、全てです。
「遠距離にあるスピーカーから音楽を流す」ことだけが目的なら実現するのは容易だと思います。
ですが今回やりたいことはそれだけではありません。
スマートフォンから、近くにあるBluetoothスピーカーへ接続するのと同じような操作感が欲しいのです。
再生するためのスピーカーにAUX端子があること(Bluetooth機能は無くてもいい)
実際のところ、遠距離のデバイスにBluetooth接続しようとするのは無謀な試みです。
なので、確実にインターネットを利用することになります。
この時点で確実に言えることは、スマートスピーカーを用いるか、それがダメなら一般的なスピーカーに対して何らかのデバイスを接続することになるということです。
デバイスからスピーカーへの接続はAUXもしくはBluetoothで行うことになるでしょう。
逆に言えば、それらが可能な何らかのデバイスが必要ということになります。
設計
どのようなデバイスやシステムをどのように組み合わせるべきか非常に悩みました。
- AppleデバイスのAirPlay機能が使えないか
- PythonのBluetoothモジュールなどを利用してスクリプトを作成するか。 作成するにしてもレシーバーとサーバーが必要になるよなあ
- Web Bluetooth API(WebブラウザからBluetoothを使用する機能)を使うべきか 作成するにしてもレシーバーとサーバーが(以下略
- Bluetooth通信データを解析し、音楽データを抽出、抽出したデータを外部端末へストリーミングし、端末からスピーカーへ再生
など…
思いついた案はどれも簡単には実現出来そうにありませんでした。
これって相当難しいことなんじゃないか…?と思い、途中諦めかけていましたが、
最終的に以下のような構成を思いつきました。
- Bluetooth接続用と音楽再生用のデバイスの2つを用意し同じネットワークに所属させる。 Bluetooth接続用デバイスで再生されている音をもう一つのデバイス(音楽再生用)へネットワーク経由で転送し、再生する。 同じネットワークに所属させるためにVPNサーバを利用する。
それを図にしてみると次のようなイメージです。

デバイスについては、手元にRaspberry Piが複数台あるのでこれらを活用することにしました。
これならスクリプトを独自に作成することもなく、既存のソフトウェアなどを利用し組み合わせるだけで実現できそうです。
動作の流れとしては次のとおりです。
- Bluetooth接続、AUX接続がどちらも可能なデバイス(今回はRaspberry Pi)を2台用意する。
- 1台はスマートフォンへ接続する用として用意、もう1台は再生したいスピーカーへBluetoothもしくはAUX接続をしておく。
- 2台のRaspberry PiをVPN接続する。
- これにより、2台のRaspberry Piが同一セグメントのネットワークに属することになります。
- スマートフォンからRaspberry Piに対してBluetooth接続を行い、音楽を流す。
- スマートフォンに接続されたRaspberry Piから、インターネット経由でスピーカー側のRaspberry Piへ音データを送信する。
- スピーカー側のRaspberry Piが、受信した音をスピーカーで再生する。
Bluetoothで送信した音楽を、どのようにインターネット経由で別のデバイスへ送信するかがこの構成を実現する上で最も重要なポイントになります。
Raspberry Pi同士で音を転送するために、Raspberry Pi OS標準パッケージであるPulseAudioの機能を用いることにしました。
調査したところ、PulseAudioにはネットワーク経由でオーディオデバイスを共有する機能があるようです。
まさか標準機能として備わっていたとは…!
そんな事に大喜びしている人がこの世にどれだけいるのやら…開発者様に感謝です。
スマートフォンからスピーカーへ直接接続するわけではありませんからね。
インターネットを経由して間接的に接続するイメージです。
使用したもの
- Raspberry Pi 4 Model B 8GB RAM
- 2年ほど前に購入し、VPNサーバとして利用しています。 長寿命化のために色々とチューニングしているおかげか、現在まで一度も故障することなく稼働しています。
- Raspberry Pi Zero W 2(ピンヘッダ無し)
- 今回思いついたものを実現するにはもう一台デバイスが必要になるため、今回のために追加で購入しました。 このモデルを選んだ理由は以下のとおりです。(重要視順) ・価格が安い ・他のRaspberry Pi シリーズと比べて消費電力が少ない ・Zeroシリーズの中では現状、最もコストパフォーマンスが高い ・実現するために必要な条件を満たしている
- ピンヘッダは別途購入して後付けしました。 VPNサーバやその他の色々な処理を同時に動かすことができるか、スペック的に少し不安ですが…大丈夫でしょう。
- microSDカード 64GB
- スピードクラスUHS-1以上のものを使用すれば問題ないと思います。
- Creative Pebble V3
- 今回はたまたま手元にあったこちらのスピーカーを使用しました。 AUX端子&Bluetooth機能付きです。
- ステレオミニプラグケーブル
- Raspberry Piとスピーカーを接続するために使用します。
- NEC Aterm WX3600HP
- ポートフォワーディング設定が可能なルータであれば何でもOKです。
環境構築
ボリュームが多いため、先に全体の流れを記載します。
1. Raspberry Pi 共通の事前準備
2. Raspberry Pi 1台目(Raspberry Pi 4)のセットアップ
3. Wi-Fiルータのポート開放
4. Raspberry Pi 2台目(Raspberry Pi Zero W 2)からVPN接続を行う
5. PulseAudioを使用してRaspberry Pi同士を接続する
6. Raspberry Piとスピーカーを接続する
Raspberry Pi 1台目はスマートフォンとのBluetooth接続に利用し、
2台目はBluetoothスピーカーとの接続に利用します。
1. Raspberry Pi 共通の事前準備
Raspberry Pi OSのセットアップ
2台とも同様にセットアップを行います。
構築時点で最新のOSを使用すれば問題ありません。
今回はGUIのないバージョンであるLite版を使用しました。
IPアドレスの固定化
VPNサーバや、Raspberry Pi同士の通信を行うために、Raspberry Pi自身のIPアドレスを固定させる必要があります。
PulseAudioのインストール
最近(少なくとも2024年以降)のRaspberry Pi OSにはPulseAudioがインストール済み、という情報を多くの記事で読みました。
ですが、今回使用するRaspberry PiにはPulseAudioがインストールされていませんでした。
その理由は、恐らくインストールに使用したOSがLite版のためだと思われます。
Lite版には、OSの実行に必要な最低限のパッケージのみがインストールされているため、PulseAudioはインストールされなかったのだと考えられます。
ということで以下のコマンドを実行し、パッケージリストの更新とPulseAudioのインストールを行います。
$ sudo apt update
$ sudo apt install pulseaudio
Raspberry Pi Zero の方は問題なくインストールできましたが、Raspberry Pi 4ではインストールの途中で以下のようなエラーが発生し、インストールに失敗してしまいました。
Setting up initramfs-tools (0.142+deb12u1) ...
update-initramfs: deferring update (trigger activated)
Processing triggers for initramfs-tools (0.142+deb12u1) ...
update-initramfs: Generating /boot/initrd.img-6.6.20+rpt-rpi-v8
xz: /var/tmp/mkinitramfs_fkePWg//lib/modules/6.6.20+rpt-rpi-v8/kernel/fs/btrfs/btrfs.ko: Write error: No space left on device
xz: /var/tmp/mkinitramfs_fkePWg//lib/modules/6.6.20+rpt-rpi-v8/kernel/fs/xfs/xfs.ko: Write error: No space left on device
cpio: write error: No space left on device
E: mkinitramfs failure cpio 2
update-initramfs: failed for /boot/initrd.img-6.6.20+rpt-rpi-v8 with 1.
dpkg: error processing package initramfs-tools (--configure):
installed initramfs-tools package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
initramfs-tools
E: Sub-process /usr/bin/dpkg returned an error code (1)
エラー内容を見てみると、以下のメッセージが出力されています。
write error: No space left on device
どうやらストレージの空き容量が不足していて/var/tmp/
への書き込みが失敗しているようです。
そんなまさか、と思いつつ、空き領域を調べてみました。
~ $ df -h
Filesystem Size Used Avail Use% Mounted on
udev 3.6G 0 3.6G 0% /dev
tmpfs 781M 2.8M 779M 1% /run
/dev/sda2 28G 3.4G 24G 13% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 16K 5.0M 1% /run/lock
tmpfs 64M 0 64M 0% /tmp
tmpfs 128M 136K 128M 1% /var/log
tmpfs 32M 0 32M 0% /var/tmp
/dev/sda1 510M 64M 447M 13% /boot/firmware
tmpfs 781M 0 781M 0% /run/user/1000
すると、/var/tmp/
は一時ファイルシステムに書き込まれるように設定されており、しかも32MBしか割り当てられていないことが判明。
OSをインストールしただけではこのような設定にはならず、通常はストレージへ書き込まれます。
どうやら、以前に自分で設定を変更していたようです。(購入してからかなり経っているので当時何をしたのか忘れていた…)
ひとまず、割り当てサイズを512MBへ拡張したところ、インストールに無事成功しました。
割とすぐに解決できましたが、このような事象が発生してしまった原因は、自分が過去に実施したストレージ長寿命化の設定が適当だったためです。
それにしても、当時の自分、なぜ32MBに設定したんだろう…
きちんと意味を理解せずに参考記事をそのまま鵜呑みにしたのでしょう。
せっかく振り返ったんだからしっかり反省しましょうね。
Bluetooth接続確認(Raspberry Pi → Bluetoothスピーカー)
次は、Raspberry PiからBluetoothスピーカーへ接続確認をします。
Raspberry PiからBluetoothを操作するために、bluetoothctlというツールを利用します。
さっそく、周囲のBluetoothデバイスをスキャンしてみましょう。
~ $ sudo bluetoothctl
Agent registered
[CHG] Controller B8:27:EB:AA:F5:89 Pairable: yes
[bluetooth]# scan on #このコマンドを入力
Discovery started
[CHG] Controller B8:27:EB:AA:F5:89 Discovering: yes
[NEW] Device 48:82:76:69:76:53 48-82-76-69-76-53
[NEW] Device 20:1C:3A:3E:6D:AF Pokemon GO Plus +
[NEW] Device FF:02:3C:B2:FF:E4 BLE MF0495
[NEW] Device 42:9A:E1:FF:46:DB 42-9A-E1-FF-46-DB
[NEW] Device FC:66:3F:35:85:B2 FC-66-3F-35-85-B2
[NEW] Device 41:1A:9D:F3:1E:44 41-1A-9D-F3-1E-44
[NEW] Device 4C:49:C4:4A:22:83 4C-49-C4-4A-22-83
[NEW] Device 71:54:46:23:24:36 71-54-46-23-24-36
[NEW] Device 7F:A4:71:E9:13:C1 7F-A4-71-E9-13-C1
[NEW] Device 69:44:38:2F:D7:8A 69-44-38-2F-D7-8A
[NEW] Device 77:13:7A:30:B5:D8 77-13-7A-30-B5-D8
[NEW] Device 6A:CD:12:1D:99:85 6A-CD-12-1D-99-85
[NEW] Device 00:02:3C:B2:FF:E4 Creative Pebble V3
おお、すごい。
こんなにたくさん検出されました。
目的のスピーカーも検出されていますね。
肌身離さず持ち歩いているPokemon GO Plus +まで検出されていて面白い。
ここで気になったのは、PCやスマートフォンのBluetooth検出では絶対に現れないデバイスが多数検出されている点についてです。
Pokemon GO Plus +については、Pokemon GOというアプリ内でしか検出されません。
少なくともbluetoothctlを使用したスキャンでは全てのBluetoothデバイスが検出されているように思えます。
PCやスマートフォンで表示される、されないという違いはどういった仕組みなのでしょうか。
気になるので別途調査してみたいところです。
ということで、検出されたスピーカーへ接続します。
[bluetooth]# connect 00:02:3C:B2:FF:E4 #接続したいデバイスのMACアドレスを指定
Failed to connect: org.bluez.Error.Failed br-connection-profile-unavailable
ところが、エラーにより接続出来ず。
調べてみると、PulseAudioをインストールした状態でBluetooth接続を行う場合、pulseaudio-module-bluetooth
という追加のパッケージが必要とのことでした。
インストール後、再起動を行ったところ、接続に成功しました。
[bluetooth]# connect 00:02:3C:B2:FF:E4
Attempting to connect to 00:02:3C:B2:FF:E4
[CHG] Device 00:02:3C:B2:FF:E4 Connected: yes
[NEW] Endpoint /org/bluez/hci0/dev_00_02_3C_B2_FF_E4/sep1
[NEW] Endpoint /org/bluez/hci0/dev_00_02_3C_B2_FF_E4/sep2
[NEW] Endpoint /org/bluez/hci0/dev_00_02_3C_B2_FF_E4/sep3
[NEW] Transport /org/bluez/hci0/dev_00_02_3C_B2_FF_E4/sep1/fd1
Connection successful
接続できたので、試しに何か音を鳴らしてみます。
speaker-testというツールが標準で使用でき、スピーカーをテストすることができるようです。
以下のコマンドを実行すると、2つそれぞれのスピーカーから音が流れてくることが確認できました。
speaker-test -c2 -t wav
これでRaspberry PiからBluetoothスピーカーへ接続する準備が完了しました。
Bluetooth接続確認(スマートフォン → Raspberry Pi)
前の節では、Raspberry PiからBluetoothスピーカーへの接続の確認を行いましたが、次はスマートフォンからRaspberry Piに対しての接続ができるかどうか確認をします。
bluetoothctlを使い、他の端末のBluetooth検索からRaspberry Piを発見できるようにします。
~ $ sudo bluetoothctl
Agent registered
[CHG] Controller E4:5F:01:4C:95:F4 Pairable: yes
[bluetooth]# discoverable on #このコマンドを入力
Changing discoverable on succeeded
[CHG] Controller E4:5F:01:4C:95:F4 Discoverable: yes
[bluetooth]# agent NoInputNoOutput #このコマンドを入力
discoverable on
を実行することで、他の端末からRaspberry Piが発見できるようになります。
agent NoInputNoOutput
は、接続時のデバイス認証で、スマートフォン側の6桁の認証コード入力をスキップし、Raspberry Pi側で接続の許可/不許可を行うための設定です。
上記のコマンドを実行すると、以下のようにスマートフォン上でRaspberry PiがBluetoothデバイスとして表示されました。(端末はiPhoneです)

表示名はホスト名のようです。
表示されたデバイスを選択すると、Raspberry Pi側で接続を許可するかどうかの確認メッセージが表示されました。
ここで、「yes」と入力することで接続が完了します。
...
[**agent**] Authorize service 0000110e-0000-1000-8000-00805f9b34fb (yes/no): yes #このコマンドを入力
[NEW] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 [default]
[NEW] Item /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0/Filesystem /Filesystem
[NEW] Item /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0/NowPlaying /NowPlaying
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Type: Audio
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Subtype: None
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Status: paused
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Browsable: yes
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Searchable: yes
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Playlist: /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0/NowPlaying
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Name: ミュージック
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Repeat: off
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Shuffle: off
[NEW] Folder /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Duration: 0x0003fcf9 (261369)
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Genre: ダンス
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Title: Metalslaves
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Item: /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0/NowPlaying/item8324769182707319864
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 TrackNumber: 0x00000004 (4)
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Artist: Pattern J
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 NumberOfTracks: 0x0000000e (14)
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Album: Digital Jolt
[NEW] Item /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0/NowPlaying/item8324769182707319864 <unknown>
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Position: 0x0000085a (2138)
[CHG] Player /org/bluez/hci0/dev_80_B9_89_96_DD_E0/player0 Position: 0x0000085a (2138)
接続に成功すると、色々な情報が表示されました。
どうやら接続側で再生している音楽の情報が表示されているようです。
音源データだけでなく、他にも様々な情報を送っているんですね。
これで、Bluetooth周りのセットアップは完了です。
WireGuardのインストール
VPN接続を行うために、VPNソフトウェアであるWIreguardをインストールします。
サーバー側とクライアント側でそれぞれインストール方法が異なります。
サーバー側は後述のPiVPNを使用してインストールを行います。
クライアント側は以下のコマンドを実行するだけで簡単です。
sudo apt install wireguard
2. Raspberry Pi 1台目(Raspberry Pi 4)のセットアップ
PiVPNのインストール、セットアップ
VPNサーバを構築するためのツールです。
インストールウィザードに従って進めることでVPNサーバの構築を簡単に行うことができます。
基本的にデフォルトの設定に従って進めていけば問題ありませんでした。
IPアドレスの固定化などもインストールウィザードで行ってくれるため便利だと感じました。
PiVPN自体はVPNソフトウェアではなく、VPNサーバを構築するためのインストーラのため、インストールするVPNソフトウェアを選択することになります。
以下の2つのソフトウェアから選択可能です。
- WireGuard
- OpenVPN
どちらを選択しても問題ありませんが、WireGuardの方が構築難易度が低いため、今回はWireGuardを選択しました。
調べたところ、パフォーマンスにおいてもWireGuardの方が優れているようです。
WireGuardクライアント用プロファイルの作成
PiVPNのインストールが完了したら、次はVPNクライアント用のプロファイルを作成します。
作成したプロファイルを、接続したい各種デバイスのWireGuardへインポートすることでVPNへ接続できるようになります。
プロファイルを作成するために以下のコマンドを実行します。
pivpn add
実行すると、プロファイルに付ける名前を聞かれるので任意の名前を入力します。
今回はvpn_clientと設定しました。
その後、~/configs
にvpn_client.confというファイルが作成されます。(ファイル名は入力したプロファイル名)
このファイルをVPN接続するデバイス(今回はもう一つのRaspberry Pi)のWireGuardクライアントにインポートすればVPN接続のセットアップは完了です。
3. Wi-Fiルータのポート開放
スマートフォン側のRaspberry Piに構築したVPNへ外部から接続するために、ルータのポートフォワーディング設定を行う必要があります。
Wi-Fiルータは、特別な設定を行わない限り、基本的に外部からの通信は全てブロックされます。
ポートフォワーディング設定により、VPNサーバを構築したRaspberry Piへの通信のみを許可します。
許可するポートは、PiVPNのセットアップで指定したWireGuardのポート番号になります。(デフォルトは51820です)
Wi-Fiルータのポート開放は、適切に設定を行わないと重大なセキュリティリスクを生む危険があるため、慎重に行いましょう。
4. Raspberry Pi 2台目(Raspberry Pi Zero W 2)からVPN接続を行う
WireGuardを用いて、スマートフォン側のRaspberry Piに構築したVPNサーバへVPN接続を行います。
WireGuardクライアント用プロファイルのインポート
前の手順で作成したプロファイルをWireGuardへインポートします。
作成したプロファイルは予めコピーしておきます。
~ $ sudo nmcli connection import type wireguard file vpn_client.conf
Connection 'vpn_client' (6b097672-0a40-47c6-a064-da7d766d345b) successfully added.
接続可能なネットワークインターフェースを確認すると、先ほどインポートしたプロファイルが確認できます。
~ $ sudo nmcli connection show
NAME UUID TYPE DEVICE
vpn_client 6b097672-0a40-47c6-a064-da7d766d345b wireguard vpn_client
次に、実際にVPNへ接続します。
切断する時はupをdownに変えます。
~ $ sudo nmcli connection up vpn_client
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
curl ifconfig.io
等を実行してグローバルIPを確認し、VPNサーバーのグローバルIPと同一になっていれば無事VPN接続成功です!
5. PulseAudioを使用してRaspberry Pi同士を接続する
本記事の中で最も重要で、かつ最も手こずりました…
音楽データ”受信”側の設定
/etc/pulse/default.pa
を開き、以下の記述を追加します。
load-module module-native-protocol-tcp auth-ip-acl=<送信側マシンのIPアドレス>
load-module module-switch-on-connect
<送信側マシンのIPアドレス>には、192.168.1.2のように、送信側マシンのIPアドレスを入力します。
load-module module-switch-on-connect
この一文は、Raspberry Piに新しいサウンド出力が追加された際に、自動的にその出力へ切り替える設定です。
つまり、Bluetoothスピーカーへペアリングした際に、サウンド出力が自動的にBluetoothスピーカーへ切り替わるようになります。
音楽データ”送信”側の設定
/etc/pulse/default.pa
を開き、以下の記述を追加します。
load-module module-tunnel-sink server=tcp:<送信側マシンのIPアドレス> rate=<サンプリングレート> channels=2
<サンプリングレート>と固定遅延(ミリ秒)>の設定は非常に重要です。
適切な設定を行わないと、受信側で音飛び(正確にはスタッタリングという)が発生してしまうためです。
<サンプリングレート>には22050または44100を設定するとよいと思います。(場合によってはもっと小さい値を)
値が大きいほど高音質になりますが、送信データ量が大きくなり、音飛びが発生しやすくなります。
<固定遅延(ミリ秒)>は、受信側で音楽データを受信してから再生を開始するまでの時間です。
時間が長ければ、その分だけデータを受信する猶予が生まれるため、遅延が発生する代わりに音飛びが発生する可能性が低くなります。
その他にも、オブションとして “latency_msec” というパラメータが指定可能で、固定遅延を設定ことができて音飛びが改善する、とのことだったので設定してみましたが、音が遅延している様子もなく、音飛びの改善が見られませんでした。
詳しく調べてみると、どうやらデータ転送にRTPプロトコル(module-rtp-recv)が使用できるらしく(通常はTCPプロトコル)、その場合のみ固定遅延が設定可能とのことでした。
RTPを使用する場合は、さらに多くの手順が必要とのことだったので、まずはTCPプロトコルでのデータ転送で進めたいと思います。
設定が完了したら、以下のコマンドを実行してそれぞれのPulseAudioを再起動します。
~ $ pulseaudio -k
~ $ pulseaudio -D
適切に設定が行われていればこの時点で、送信側で再生した音楽が受信側で再生されるようになります!
6. Raspberry Piとスピーカーを接続する
今回はRaspberry Piとスピーカーをステレオミニプラグで接続しようと思います。
と、ここであることに気が付きました。それは…
“Raspberry Pi Zeroシリーズにはイヤホンジャックが搭載されていない”
手元にあるにも関わらず、Raspberry Piシリーズには全て搭載されているものと思い込んでいて全く気が付きませんでした…
という訳で、仕方なくBluetooth接続を行うことにしました。
ステレオミニプラグで接続したかった理由は、ステレオミニプラグの方が手っ取り早く接続できるのと、接続と通信が安定しているためです。
Bluetoothの場合、接続が切断されてしまったり、通信が安定しない等のケースを考慮する必要があります。
スピーカーと、それに接続されているRaspberry Piは手元に無く、遠距離に設置してある想定のため、スピーカー側に何か問題が発生した場合に対処するのが難しくなります。
最低限、切断されてしまった場合に自動的に再接続を行う仕組みは構築しておく必要がありそうです。
ここまで構築が完了すれば、いよいよ実際に動かすことができます!
まずは自宅で動作確認
いきなり遠隔地で試す前に、まずは自宅で動かして確認したいと思います。
2台のRaspberry Piが同じWi-Fiに接続しているので、VPN接続はせず、その他は同じ条件で構築します。
結果、無事音楽を再生することができました。
音の遅延についても、時々一瞬途切れる程度で、ほとんど問題なく再生できました。
VPN接続がどのくらい影響するのか気になりますが、実現できることは分かったので、実際に遠距離から再生するためにスピーカーとRaspberry Pi Zeroを自社の事務所へ持っていき実験してみたいと思います。(もちろん許可は得ています)
自宅 ←→ 事務所 で試してみた結果…
成功…??
試しにiPhoneから音楽を流してみた様子を撮影してみました。
事務所に設置済みのBluetoothスピーカーを別途カメラで動画撮影し、配信している様子をさらに別のカメラから動画撮影しています。
なので、以下の動画は自宅から撮影していますが、聞こえてくる音は事務所にあるBluetoothスピーカーから流れている音になります。
撮影協力していただいたIさん、ありがとうございました。
遅延がひどすぎて撮影しながら笑ってしまいました…
一応、音を鳴らすことはできたので、仕組みとしては実現することができました。
まあ、この状態では実用には程遠いですね…
VPN接続をしながらデータのストリーミングを行っているので、ネットワーク通信速度の影響を大きく受けていそうです。
さらに、Raspberry Piが接続している二拠点それぞれのネットワークが良好でないといけないので、途切れず再生するための条件は結構厳しそうに思えました。
有線接続を行えば安定すると思うので多少は改善されるかな…?
根本的な改善策として最も有効と考えられる方法は、データ転送プロトコルをTCPからRTPへ変更することだと思います。
このままでは悔しいので、RTPへ変更して改善できるかどうか今後試してみたいと思います。
構築している間はずっとRaspberry Pi Zeroのスペックがボトルネックにならないか不安でしたが、価格的に低コストなRaspberry Pi Zeroでも実現可能であることを実証できたのは嬉しかったです。
もしかしたら更に低スペックなRaspberry Pi Picoでも大丈夫かもしれません。
持っていないので、いつか購入して遊んでみたいです。
未だにまともな用途が思いつかないので、とりあえず遠隔地から急に音楽を流してびっくりさせるドッキリでも仕掛けようと思います。
ハマった点
iPhoneのサウンド出力候補としてRaspberry Piが表示されない
PulseAudioのサービスが立ち上がっていないことが原因でした。
PulseAudioインストール後に再起動を行えばすぐに気が付くような話でした。
原因がよく分からず、Raspberry Piがオーディオ機器として認識されていない線を疑ったりして2、3時間ハマってしまいました。。
そのほか
英単語の前後のスペースについて
普段テキストを書く際、英単語の両端にスペースを入れますが、ブログ記事のような長文の場合、スペースを入れるのが大変だということに気が付き、スペースを入れるのをやめました。
スペースを入れる、入れないの判断については、チャットなどの短い文章を書く際はスペースを入れる、長文だけど読みやすさや、速さ、丁寧さを重視するかなど、場面に合わせて使い分けていこうと思います。
上手くいった時の喜びについて
構築当時、PulseAudioの設定項目の一つであるmodule-tunnel-sinkという設定の存在を見つけて、使い方を理解するまでに相当な時間が掛かりました…
どのような設定をすれば目的が果たせるのか見当がつかなかったので、公式ドキュメントを隅から隅まで読み漁りました。
目的のものが見つからない(見つけられない)かもしれないという不安が常にあるため、かなり辛い作業でした。
しかし、たどり着いたときの達成感はとてつもなく、「よっしゃー!!」とバンザイしてしまいました。(本当です)
これは「ハマる」ことのメリットの一つだと思っています。
逆に、どうしようもなくて諦めてしまったときの悔しさも同じです。
自分は諦めが悪い性格なので、諦めてしまったらしばらく引きずってしまうかもしれません…
記事の内容は以上となります。
最後までお読みいただきありがとうございました。