複数のAirPods接続時のAudioの挙動 – FILM REDの副音声上映で困った原因を追究する –
この記事はpotatotips #81 iOS/Android開発Tips共有会で発表した時の内容をまとめたブログになります。スライドは以下から確認できます
テーマきっかけの経緯
ある日、ONEPIECE FILM REDの副音声上映を友達と見に行きました
副音声上映とは、専用アプリを使って、副音声を聴きながら映画を見る上映方法です(アプリのサイト)
専用アプリを起動した状態で映画を見ると、その映画の音声を拾って、それに合わせた時間の副音声をながしてくれるので、それをイヤホンで聴くというスタイルです
しかしトラブルが。。
友達が副音声アプリのことを知らなかったので、映画館にイヤホンを持ってきていない&アプリをインストールしていなかった
おまけにスマホのバッテリー残量も全然ない
このままでは友達が副音声を聴くことができない。。。
そこで解決策をひらめく🙄
- 自分はメイン使用のAirPodsProと予備のBeatsのイヤホンをいつも持っている
- 自分はメイン使用のAirPodsProと予備のBeatsのイヤホンをいつも持っている
- W1/H1チップ搭載のBeatsのイヤホンも対象
発表者のiPhoneに2つのイヤホンを接続して、発表者と友達がそれぞれイヤホン装着すれば、解決では??
しかしトラブルが発生!
事前にYouTubeで2台同時に接続した状態で両方とも音声が流れることを確認したが、いざ映画が始まると自分のBeatsのイヤホンの音声だけが聞こえない。。
友達にこっそり確認すると、友達のAirPodsは聞こえているっぽい
上映中なので、細かく調査することもできない。。
上映中に大パニックになり、冒頭のライブシーンをほぼ聴き逃す。。
結局映画はAirPodsを2人で1つずつ付けて聞きました!
この経験から、もしかして実装の設定次第で、AirPodsの接続の仕方が変わることがあるのでは
と思って、これは調べるしかない!と思って、調査することにしました!
調べたこと
今回調査したのは以下の内容です
- 今回の事象の再現
- 音声再生時に、AVAudioSessionでどのような設定をすれば、2台接続していたAirPodsが1台にのみ接続されるようになるか
- 2台接続時のAVAudioSessionの挙動
- コードの実装で何ができるかの調査
今回の事象の再現
結論としては、以下の設定で1つのAirPodsしか繋がらなくなるという事象を再現できました
詳細の仕様やドキュメントは見つけられませんでした。。
ちなみにイヤホンが1つしか接続していない時に、もう一つのAirPodsを選択すると、端末のスピーカーに切り替わるという挙動も確認してます
do {
var output = AVAudioSessionDataSourceDescription()
try session.setCategory(.playAndRecord, mode: .default, options: [.allowBluetoothA2DP, .mixWithOthers])
try session.setActive(true)
} catch {
print(error)
}
言語化すると、AVAudioSessionのsetCategory()のメソッドを以下の設定で実行することで再現しました。
- category: .playAndRecord
- options: ↓の両方を満たす
- .allowBluetooth or .allowBluetoothA2DP
- .mixWithOthers or .duckOthers
再現環境
- iOS16.2
- Xcode14.2
2台接続時のAVAudioSessionの挙動
調査前は以下のようになるかな?と仮説を立てていました
○仮説
AVAudioSession.sharedInstance().route.outputsの配列から、AirPodsの情報が2つ取得できる?
○確認結果
- 1つのAirPodsの情報しか取得できない
- どのAirPods情報が取得できるのかの法則は確認できず。。
- ちなみに設定適応時に一瞬音が途切れる
実際にprintしてみても、1台のAirPodsしか取得できない↓
for desc in route.outputs {
print("PortName: \(desc.portName), PortType: \(desc.portType)")
}
// PortUID: xx:xx:xx:xx:xx:xx-tacl, PortName: Yugos-AirPodsPro, PortType: BluetoothA2DPOutput
接続されるAirPodsや上記のprintされるイヤホンがどちらになるのか、以下の観点で確認してみました
- AirPodsPro->Beatsの順で接続
- 基本AirPodsProだけが接続状態になる&printされる
- Beats->AirPodsProの順で接続
- Beatsだけが接続状態になる&printされる
しかしたまに以下のようになる時があった。。
- たまに接続: AirPodsPro&Beats: printのように、接続している&printされるイヤホンが一致しない場合がある。。(なんでだ??)
ちなみに2台のAirPods接続時に電話がかかってきた時も1台のAirPodsのみ接続状態になるのですが、その場合は以下のような挙動になりました
- AirPodsPro->Beatsの順で接続
- Beatsにだけ着信メッセージが流れる
- Beats->AirPodsProの順で接続
- AirPodsProにだけ着信メッセージが流れる
アプリでの検証と真逆の結果に混乱する自分。。
まとめ
- AVAudioSessionの設定次第で、AirPodsを複数台接続した時に、片方のAirPodsしか繋がらなくなる時がある
- 正確なルールや仕様は不明で、実際の挙動から推測することしかできない
- イヤホンの接続順が関係ありそうな気がする
- アプリについて困ったことで調べられるのはエンジニアの特権!
- 音声系のアプリは、AirPods2台接続した時の動作確認も必要!?
- もしこの辺りの挙動に詳しい人、もしくは今回の発表内容で間違っている点があれば、ご指摘を!