iPhoneでも、Apple Musicのボーカルを消す――HeyaKaraを動かすために越えた三つの壁
今度は、Macを持ち歩かずに
前回の記事では、Macで鳴っている曲からボーカルを消し、キーを変えてヘッドホンへ返す自作アプリ「HeyaKara」を紹介した。オフボーカル音源を探さなくても、いつもの曲で歌えるようにする仕組みだ。
今回は、その続きをiPhoneで作った。DRM付きのApple Music配信曲でも、再生音を受け取り、iPhoneの中でボーカルを分離できる。 DRMとは、音楽などの利用を制御する保護の仕組みのことだ。ここで扱うのは、曲ファイルを読み出して加工する方法ではなく、ミュージックアプリが再生した音を受け取る方法である。
ここで紹介するのは、iOS 27以降を対象に、自分の端末へインストールして使う開発版だ。2026年10月16日の実機確認では、Apple Musicの配信曲を取り込み、分離した音を再生できた。ホーム画面に戻っても、画面をロックしても音を出し続けるところまで確認している。ただし、すべてのiPhoneや曲での動作を確認したという意味ではない。
操作の入口は、音楽を鳴らすときの「出力先」だ。HeyaKaraで受信を準備してから、ミュージックアプリの出力先一覧で、このアプリが用意した音声経路を選ぶ。本体に戻って処理を始めると、少し待って、ボーカルを抑えた音が鳴る。Macへ音を送って処理しているわけではない。
使う側から見れば出力先を変えるだけだが、実装はMac版の単純な移植では済まなかった。難所は三つあった。音をどう受け取るか、途切れずにどう分離するか、画面を閉じてもどう動かすか。
壁1:曲を選べても、その音を読めるとは限らない
iPhone版には、端末内の音声ファイルや、ミュージックライブラリの曲を選んで処理する経路もある。この経路では、音声を順に読み出すAVAssetReaderを使い、AIへ渡せる波形にする。
しかし、ライブラリに曲名が見えていることと、その曲の波形をアプリが読めることは別だ。今回の実装でも、保護された曲はファイル読み込みの対象から外している。Apple Musicのサブスクリプション曲は、ダウンロード済みであっても、この経路で分離する対象にはならない。
そこで、入口を二つに分けた。
| 入力 | 音を受け取る方法 | 今回の使い分け |
|---|---|---|
| 手元の音声ファイル、端末内のDRMなしの曲 | ファイルの音声を読み出す | 読める音源を直接分離する |
| Apple Musicの配信曲 | 再生アプリの出力先として音を受け取る | 配信曲のボーカルを抑えて聴く |
表は実装上の入力経路を整理したもの。保護状態の判別はAppleが公開するhasProtectedAssetの仕様を参照した。
Mac版では、特定のアプリの音を取り込むProcess Tapを使った。iPhone版は、そのコードをそのまま移す設計にはしていない。HeyaKara自身を、音楽の送り先として選べるようにする設計に変えた。
出力先一覧に、音を受け取る拡張を置く
使ったのは、AppleのMedia Device拡張だ。テレビやスピーカーなど、音や映像の送り先をシステムの出力先一覧へ追加するための仕組みである。
ユーザーが送り先を選ぶと、OSが拡張へ接続を要求する。拡張は接続の準備をして、音を受け取れる状態になったことをOSへ返す。Appleの拡張作成ガイドは、この発見・選択・接続の流れを説明している。
ここで注意が必要なのは、出力先として一覧に出ることと、実際の波形が届くことは別の段階だという点だ。
拡張には、リアルタイムの音や映像を受けるためのRealtimeSampleHandlingを実装する。これはiOS 27以降の仕組みで、Appleの資料でも、音声サンプルの受信にはAudioServerDriverを使う構成が示されている。今回の実装は、Core Audioの出力ドライバを登録し、そこへ届くPCM――音の波形を数値で表したデータ――を取り出している。
つまり、「接続できました」という通知だけでは分離は始まらない。出力ドライバまで用意して、初めてAIに渡せる音になる。リアルタイム受信の公式仕様と、実装した音声受信部分を突き合わせて確認した箇所だ。
図:実装をもとに編集部で整理した音の流れ。図の処理はすべて同じiPhoneの中で行う。配信曲のファイルや復号鍵を取得する処理は、この経路にはない。
Apple Musicの原音を、どうやって鳴らさないようにしたのか
音を受け取るだけでは、カラオケにはならない。Apple Musicから元の歌入りの音が直接聞こえ、その十数秒後にHeyaKaraの伴奏も聞こえたら、二重再生になってしまう。必要なのは、元アプリの再生を続けながら、耳に届く音を加工後のものに置き換えることだ。
Mac版は、Process Tapの.mutedWhenTappedで、取り込み中の元アプリの音をミュートした。iPhone版では、Apple Musicの音の送り先を、受信用の経路へ切り替えることで実現している。選んだ先は、実際に音を鳴らすスピーカーではなく、波形を受け取るために用意した出力先だ。
受信側のドライバは、その波形をHeyaKara本体へ渡す。この段階では、未加工の音をヘッドホンなどへ再生する処理を入れていない。ヘッドホンなどへ音を出すのは、分離を終えたHeyaKara本体の役割になる。Apple Musicは再生を続けるが、その原音を直接は鳴らさず、加工後の音だけを聴くという流れだ。
本体の再生設定にも注意が要る。加工音を鳴らし始めたことで、音の供給元であるミュージックアプリが止まっては困る。そこで、AVAudioSession――アプリの音声利用をOSへ伝える設定――を、次のようにしている。
let session = AVAudioSession.sharedInstance()
try session.setCategory(
.playback, mode: .default, policy: .default,
options: [.mixWithOthers]
)
try session.setActive(true)
mixWithOthersは、ほかのアプリの音声セッションを中断せず、自分の音も再生するための設定だ。Appleの仕様でも、その役割が説明されている。この設定が原音を消すわけではない。原音が直接聞こえない理由は、先に説明した出力先の切り替えにある。
さらに、加工音の出力先が受信用の経路へ戻ると、加工した音をまた取り込む循環ができてしまう。本体は出力先を確認し、受信用の経路やAirPlayへの出力を検出した場合は処理を止める。原音を受け取る入口と、加工音を聴く出口を分けて保つところまでが、この仕組みの実装だ。
受信用の補助アプリを分けた理由
構成上は、分離する本体とは別に、受信用の拡張をインストールする補助アプリが必要になった。
これは画面を分けたかったからではない。Appleの仕様では、Media Deviceの権限を拡張と、その拡張を収めるアプリの両方に付け、収める側のアプリの用途を拡張の配布・インストールに限定する必要がある。そのため、受信用拡張を届ける役と、AIで音を加工する役を別にしている。権限の公式仕様にある制約に合わせた構成だ。
拡張から本体への音の受け渡しには、端末内だけで完結する通信を使う。接続時には共有した鍵で互いを確認し、接続相手を確かめてから波形を渡す。クラウドへ送って分離する構成にはしていない。
壁2:AIが速くても、音はそのままではつながらない
音が届けば、次はボーカル分離だ。ここは前回の資産を使えた。Mac版と共通の音声処理と、Core MLで動かす分離モデルを利用する。Core MLは、Appleの端末上で機械学習モデルを動かすための仕組みだ。
ただし、入力とモデルの条件はそのままでは合わない。今回の受信経路の音は48 kHz、分離側は44.1 kHzなので、サンプルレート――1秒の音をいくつの数値で表すか――を変換する。その後、6秒ぶんを切り出し、隣の区間と1秒重ねて分離する。重なった部分を滑らかにつなぐので、継続して受け取る音から、おおむね5秒ごとに新しい加工音ができる。
受信のたびに、その場で重いAI処理をするわけではない。音を受ける側は、まず容量の決まった待ち行列へ波形を渡す。分離は別の処理列で進める。受信と推論を切り離しておかないと、AIの処理待ちが、音を受ける作業まで止めてしまう。
この入口では、最初の準備も大事だった。モデルを読み込んだ直後、実際の曲を処理する前に、同じ形の入力で試運転する。初回に必要な準備を、音楽の連続処理へできるだけ持ち込まないためだ。
モデルを変えれば、楽器もリアルタイムで分けられる
この記事ではカラオケ用のボーカル分離を中心に紹介しているが、同じ受信経路で扱えるのは歌声だけではない。対応する分離モデルと、楽器別に分ける設定へ切り替えれば、ギター・ベース・ドラムなどもリアルタイムに分離できる。
音を受け取り、区間ごとに分離して、つなぎ直す流れは共通だ。分離器が返した各パートにそれぞれの音量を掛け、足し合わせて再生する。再生しながら楽器ごとの音量を調整できるので、ギターを抑えて自分で弾く、ベースを目立たせて聴く、といった使い方にもつながる。
ただし、分けられる楽器と分離の品質はモデルによる。任意のモデルを入れれば何でも分けられるわけではなく、アプリが扱える形式・出力の構成に対応している必要がある。リアルタイムで鳴らし続けるには、そのモデルの処理が端末上で音の到着に追いつくことも条件になる。
待ち時間を減らすか、音切れを減らすか
分離できた音も、すぐに全部鳴らし始めればよいわけではない。次の区間の計算が間に合わなければ、再生が空になる。そのため、加工音をある程度ためてから鳴らす。
一方で、ためるほど操作への反応は遅くなる。ミュージックアプリで再生を押した瞬間と、HeyaKaraから音が出る瞬間は一致しない。開発資料での初回遅延の目安は約12〜20秒で、モデルの準備や音をためる時間を含む。全端末で測った値ではないが、即座に音が出るプレーヤーとは使い勝手が違う。
今回の用途では、伴奏を聴いて歌うための連続性を優先した。ただし、操作を押した結果がすぐ返ってほしい場面では、この遅れが欠点になる。
| 待たせる場所 | 実装上の上限 | 上限を設ける理由 |
|---|---|---|
| 分離する前の入力 | 8秒ぶん | 処理が遅れたとき、未処理の音をため続けない |
| 再生予約した加工音 | 12秒ぶん | 遅延とメモリ使用量が増え続けるのを防ぐ |
表は実装の設定値。上限を超えたら、無制限に待ち時間を増やさず、処理を停止して知らせる。入力と出力の上限を足した値が、そのまま通常の遅延になるわけではない。
もう一つ細かいが効いたのが、「あと何秒ぶん残っているか」の数え方だ。5秒の加工音をひとかたまりとして数え、最後まで鳴ってから5秒ぶん減らすと、途中まで再生済みなのに、まだ全部残っているように見える。次の加工音が来たときに、上限超過と誤判定しかねない。
そこで、分離は大きな区間で行い、再生の残量は0.1秒単位で管理するようにした。AIへ渡す単位と、再生待ちを数える単位を分けたわけだ。
なお、曲を変えたり先頭へ戻したりしたときは、古い曲の再生待ちと、計算中だった古い結果を破棄する。入力だけを切り替えても、待ち行列に前の曲が残っていれば、操作した後に前の伴奏が鳴ってしまうからだ。
壁3:音を鳴らし続けることと、AIを動かし続けることは別
iPhoneらしい難しさが、画面ロックだった。前面で音が出ても、ほかのアプリへ移った後にAIが次の区間を計算できなければ、ためていた音を鳴らし終えたところで止まる。
今回の実装では、背景で音を再生するためのaudioモードに加えて、BGContinuedProcessingTaskを使った。ユーザーが始めた処理を、アプリが前面から外れた後も続けるための仕組みだ。再生を続ける役と、次の伴奏を作り続ける役を、それぞれ用意する必要があった。
ここで「iPhoneにはGPUがあるから、背景でもそれを使えばよい」とはならない。背景でGPUを使うには権限が必要で、さらにOSがその端末で利用可能と返す必要がある。Appleの長時間処理のガイドも、supportedResourcesでの確認を求めている。
確認に使ったiOS 27.0.1の端末では、GPU用の権限を付けても、OSが背景GPUを利用可能とは返さなかった。そのため、この端末ではCPUで分離する経路を使った。モデルを呼ぶ側も、CPU専用かCPUとGPUの併用かを、利用条件に合わせて選んでいる。
処理を続ける許可は、音が来てから求める
開始の順序にも落とし穴があった。出力先がまだ選ばれておらず、音も届いていないのに継続処理を要求すると、実際には仕事が進まない。実装記録では、この状態でOSが処理を終了する問題に対応している。
そこで、待受と継続処理を分けた。
- HeyaKaraで分離器と受信の準備をする。
- ミュージックアプリへ移り、受信用の出力先を選ぶ。
- 実際の音が届いた後、HeyaKara本体へ戻る。
- その時点で継続処理を要求し、許可されたら背景でも分離と再生を続ける。
進捗も、単にタイマーを進めて作るのではなく、届いた音と分離し終えた音の量から報告する。画面ロックへ移るだけで分離器や再生待ちを初期化することも避けた。そうしないと、ロックするたびに最初の待ち時間へ戻ってしまう。
ただし、これは永久に動き続ける保証ではない。OSが処理を終了した場合や、ユーザーがロック画面の処理表示から停止した場合は、受信と音声処理を終了する。
実機で確認できたこと、まだ言えないこと
10月16日の記録では、Apple Music配信曲を入力にして、ホーム画面と画面ロック中の分離・再生を確認した。最終の確認では、画面ロック中に335秒、つまり5分35秒ぶんの分離と再生が継続し、記録された再生待ちの枯渇は0件だった。
これは、共通の受信・分離・再生経路についての試験である。ボーカル専用設定の処理速度や、歌声がどれだけ消えたかを測ったベンチマークではない。この記事のために再測定した結果でもなく、開発時の記録を確認したものだ。実機確認の抜粋と検証範囲を併せて公開する。
ここから言えるのは、「iPhoneだけで配信曲を受け、分離し、ロック中も鳴らす経路が実際に動いた」というところまでだ。すべての曲で声がきれいに消えるか、長時間の電池消費や発熱がどうか、別の端末でも同じ条件で動くかは、この記録だけでは判断できない。
前回と同じく、今回紹介した配信音の連続処理では、受信音と加工音をメモリ上で扱い、音声ファイルには保存しない。保存する診断情報は、処理した量やエラーなどの数値・状態である。これは実装上の説明であり、配信サービスの利用条件についての判断を示すものではない。
iPhone版の本題は、AIへ音が届くまでと、その後だった
ボーカルを分離するAIそのものは、Mac版で使った仕組みを引き継げた。iPhoneで難しかったのは、その前後だ。
配信曲をファイルとして読めなくても、再生音を受け取る入口を作る。入力を止めずに、区間ごとに分離する。画面を閉じても次の伴奏を作り、待たせすぎない範囲で音をつなぐ。この三つをそろえて、ようやく「iPhoneでいつもの曲を流して歌う」に近づいた。
使いやすさを判断する基準も、分離のきれいさだけでは足りない。再生を押してから待てる時間で、画面を閉じても伴奏が続くか。 iPhone版では、そこまで含めてカラオケ用の道具を作る必要があった。
コメント
まだコメントはありません。