世界を動かす技術を、日本語で。

自分だけのオーディオプレーヤーを作りました

概要

  • 2025年のiPhoneでは、自分の音楽ファイル再生が困難であり、Appleの有料サービスや制限を回避する必要がある現状を説明。
  • その課題を解決するため、独自の音楽プレーヤーアプリをゼロから開発した経緯を紹介。
  • iCloud対応、全文検索、ローカル優先設計など、主要な技術的特徴を解説。
  • React NativeからSwiftUIへの技術選択の流れと理由を詳述。
  • SQLiteを用いた全文検索やiOSファイル管理の実装ポイントを整理。

iPhoneで自分の音楽を再生する困難さと独自プレーヤー開発

サブスクリプション依存とAppleの制限

  • iPhoneで 自分の音楽ファイル再生 は、Apple MusicやiCloudの 有料サービス を利用しないと実現が難しい現状を確認。
  • Apple Music解約後は iCloud Music Libraryの同期機能 も利用不可となり、iTunes Match(年額$24.99)で部分的に復活するが、 オリジナルファイル管理や柔軟性 に課題が残ることを認識。
  • サブスクリプション型の第三者アプリも多く、 所有ファイル再生という単純なニーズ に対して不満を感じるユーザーが多いことを確認。

公式・サードパーティアプリの現状

  • AppleのFilesアプリでは 音楽再生機能が限定的 で、プレイリスト管理やメタデータ並び替え、キュー管理などが不十分であることを確認。
  • サードパーティ製アプリ(例:Doppler)は 単体課金モデル も存在するが、iCloudからの大量インポートや全文検索機能が弱く、 理想的なUXに到達していない ことを確認。

技術選択と開発プロセス

React NativeからSwiftUIへの移行

  • 最初は React Native/Expo で開発を開始し、Web開発経験を活かそうとしたが、 iCloudディレクトリの深い階層探索やファイルアクセス制限 で多くの問題に直面。
    • expo-filesystem等のライブラリは 大規模なフォルダの再帰処理に弱く、アプリクラッシュが発生しやすい状況を確認。
    • iOSのサンドボックス制約により、 外部フォルダへの安定アクセスが困難 であることを実感。
  • SwiftUI へ切り替え、宣言的UIと async/await・Swift Actors によるデータ同期・並列処理のしやすさを評価。
    • ViewModel分離により LLM(OpenAI o1, DeepSeek等)によるUIコード生成 の効率化も実現。
    • AppleネイティブAPI活用で iCloudファイルアクセスや権限管理 が容易になったことを確認。

アプリ構成とデータモデル

  • SQLite を用いた永続データストアを選択し、スキーマ制御や全文検索(FTS5)を重視。
    • CoreDataは 柔軟なクエリや全文検索 が難しいため採用せず。
  • アプリは 3画面構成 で以下の機能を実装。
    • ライブラリインポート画面:iCloudフォルダ選択・スキャン・DB登録を実行。
    • ライブラリ管理画面:追加済み楽曲のプレイリスト・管理・整理を実現。
    • プレーヤー画面: キュー管理(リピート・シャッフル)や再生操作 を実装。
  • ユーザーフロー例:
    • 初回起動時はSyncタブで「Add iCloud Source」ボタン表示→フォルダ選択→インデックス化→Libraryタブへ遷移→曲選択でミニプレーヤー起動→必要に応じてSyncで追加フォルダインポート可能。

バックエンド的なロジックレイヤー設計

  • サーバアプリ的な レイヤードアーキテクチャ を採用し、UI/ViewModel層とドメインロジック層を明確に分離。
    • SQLiteが最下層で生データ・FTSインデックスを保持。
    • Repository層が非同期APIを提供し、その上にSwift Actorによる ビジネスロジック(インポート・検索・キュー管理) を実装。
    • ViewModelはActorからデータを受け取りUI用Structへ変換、SwiftUIビューはそれを描画するのみとすることで 疎結合設計 を実現。

SQLiteによる全文検索実装

FTS5テーブル設計

  • iOS 11以降は SQLite FTS5拡張が標準搭載 されており、サードパーティ依存なしで 高速なファジー検索 を実現。
  • SQLite.swiftライブラリで通常クエリ、FTSは生SQLで実装。
  • FTS5テーブルは2種用意:
    • 楽曲インデックス用(artist, title, album, albumArtist列)
    • フォルダインポート用パスインデックス(fullPath, fileName列)
  • テーブル例:
    CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
      songId UNINDEXED, artist, title, album, albumArtist, tokenize='unicode61'
    );
    
    • unicode61トークナイザーで多言語対応。
  • 追加・更新は トランザクションで安全に処理 し、インデックスの不整合を防止。

ファジー検索とランキング

  • ユーザー入力に自動でワイルドカードを付与し、 部分一致検索 を高速化。
  • SQLiteのbm25ランキングを利用し、 関連度の高い結果を上位表示 することを実現。
  • 例:
    SELECT s.* FROM songs s
    JOIN songs_fts fts ON s.id = fts.songId
    WHERE songs_fts MATCH ?
    ORDER BY bm25(songs_fts)
    LIMIT ? OFFSET ?;
    

iOSファイル管理とブックマーク運用

  • iOSでは セキュリティスコープ付きブックマーク がmacOSのみ対応で、iOSでは通常のブックマークのみ利用可能。
  • ブックマークの有効期限切れや権限リセットに備え、 ファイルをアプリ内サンドボックスへバックグラウンドコピー することで、 再生時のパス不整合リスクを回避 することを重視。

このように、 Appleの制約や既存アプリの限界 に対して、自作プレーヤーを開発し、 全文検索・ローカル優先・iCloud連携 を実現した技術的アプローチと設計思想を体系的に整理した。

Hackerたちの意見

これはいい読み物だね、まだ読み終わってないけど。開発者が決める細かい詳細やその理由について読むのが好きなんだ。正直言うと、音楽アプリの中で試したプレーヤーはどれも好きじゃないけど、画面やUIのレイアウトはほとんど共通してる気がするし…なんかピンとこないんだよね。どの音楽アプリとも戦ってる気分だよ…新しいものを作ろうとする人には感謝してる。

Music.appでローカル音楽を管理して、FinderでiPhoneと同期するのはまだうまくいってるけど、Music.appはここ数年メンテされてないみたいで、ひどいBig Surのリライト以来、いくつかのイライラするバグがあるんだ。それでもこの組み合わせは、見た中で最高の音楽ライブラリ管理とモバイル同期のソリューションだと思う(おすすめあったら教えて!)、でもソフトウェアがメンテされてないしクロスプラットフォームじゃないから、最終的には自分でシステムを書かなきゃいけなくなると思う。

Musicの「リライト」の問題の一部は、実際にはリライトというよりiTunesからのコピペに近いってことだね。OS 9時代からの名残のようなモーダル設定/プリファレンスウィンドウなど、iTunesの quirks がたくさん残ってる。私の予想では、最近出たWinUIベースの新しいWindows版Musicに似た、ゼロからの本格的なリライトが進行中なんじゃないかな。

私の5世代のビデオiPodでは、Finderの同期がまだすごく壊れてる。最もイライラするのはポッドキャストの同期を試みたときで、iTunesを使ってた頃は問題なかったけど、Big SurのFinder同期を使うとバグが多くて、他のトラック/ポッドキャストに移動して戻るとポッドキャストの再生位置を覚えてくれないから、数分以上のポッドキャストはデバイスで使えなくなっちゃう。

僕のアプリも試してみてよ: https://www.plastaq.com/minimoon

フルアルバムを聴きながら休憩したりデバイスを切り替えたりできるウェブアプリを作ったんだ。アルバムを最初から最後まで聴くのが好きなんだけど、少なくともYouTube Musicは再生位置を覚えてくれないし、他のデバイスに切り替えるときにアルバムを再度開いて、どこまで聴いたかを探さなきゃいけないのが面倒なんだ。私のウェブアプリではURLを貼り付けると、yt-dlpを使ってサーバーにダウンロードされて、そこからストリーミングできるんだ。再生位置を常に覚えてくれるから、車ではスマホで聴いて、仕事のノートパソコンではその続きから聴けるんだ。他のソースからのミックスを追加するのにもすごく便利で、NTS Radioみたいな私のお気に入りにも対応してるよ。

あなたが言ってることは、YouTube Musicに対する私の最大のフラストレーションの一つだね。キューを保存したり、デバイスをもっとスムーズに切り替えられたらいいのに。もしあなたのウェブアプリが利用可能なら、ぜひ見てみたいな。

最初はSwiftを避けてたんだ、以前の経験から […] 当時はネイティブのasync/awaitがなかったから、GoやJS/TSと比べて並行コードを書くのがもっさりしててボイラープレートが多かった。私は反対だな。Asyncは並行コードを書くのを簡単にするかもしれないけど、成長するにつれて考えるのが難しくなることもある。複雑なasyncコードベースでは、コードの流れや並行性を考えるのが難しいと感じる。スレッドコードの実行コストを下げるのが目的なら、軽量スレッドのグリーンライトという解決策がある。スレッドコードのメンテナンスコストを下げるのが目的なら、長期的にはasyncがもっと手間がかかる結果になると思う。

でも、彼の使い方だと、シンプルなオーディオプレーヤーが欲しいだけだから、これが問題になることはないと思う。

非同期は同時実行コードを書くのを簡単にするかもしれないけど、成長するにつれて理解しにくくなることもあるよね。複雑な非同期コードベースでは、コードの流れや同時実行性を理解するのが難しくなる。良い同時実行性は、コードが成長するにつれて理解しやすくするべきだと思う。プロセスやサービスベースのカプセル化を持つだけでも大きな勝利だよ。俺の意見では、これは非同期/待機の抽象化の失敗であって、同時実行性そのものの問題じゃない。

私はWinampが音楽プレーヤーの定番だった時代から来たんだ。今でもストリーミングサービスの時代でも、フォルダに整理されたローカル音楽ライブラリを持ってる。だから、ここにいる他の人たちと同じように、オフラインで音楽を聴くために昔風の音楽プレーヤーを趣味で作ったんだ。1ページのhtml/jsアプリで、フルキーボードコントロールがあって、シンプルなキュー機能もあるよ。見てみてね: https://nobsutils.com/mp

僕にとって、音楽プレーヤーはずっとfoobar2000だったよ。(今日はCogアプリに変わったけど)

これ、めっちゃいいね!ナイス!

俺も言いたいことがあって、27年経った今でも、ウィナンプのUIが一番だと思ってる。シンプルでいいよね: * ディレクトリにファイルが集まってる * コレクション全体をランダム再生するか、特定のディレクトリだけ再生する機能

今でもApple Musicアプリを自分のローカルファイルと一緒に使ってる。Apple Music(ストリーミングサービス)はオフにして、Apple Music(macOSのアプリ)に全部入れたんだ。そしたら、2007年みたいに携帯をノートパソコンに繋いで、iPodみたいに同期した。すべて問題なく動いてるよ。音楽はあまり変わらないから、同期も特に問題ないし、ケーブルで同期する時にちょっと懐かしい気持ちになるんだ。

自動Wi-Fi同期はiTunesにまだ問題なく動いてると思うよ。

記事が物理デバイスと曲を管理・再生するソフトウェアについても触れてくれることを期待してたんだ。数年前、10歳の息子にMP3プレーヤーを買おうと思ったんだけど、音楽を聴くのが好きなのに、まだ(今も)電話には早いって感じだった。MP3プレーヤーの選択肢にショックを受けたよ。AppleがiPodを廃止したとき、誰も埋められない大きな隙間ができたと思う。iPod shuffle(USBスティック型)が今までで一番良いMP3プレーヤーだったと思う。小さくて、余計なコードなしで繋げられて、バッテリーもすごく長持ちした。音楽をブラウズするための画面はなかったけど、それがアイデアの一部だったんだ。ただシャッフルに任せるっていう。こんなシンプルなコンセプトすら、ハードウェア市場では再現されてないんだ。人々はそれがハードウェアの問題じゃなくて、ソフトウェアやDRMの問題だと言うけど、それは本当に残念だと思う。僕の音楽を再生するための良い、安価でポータブルなデバイスがあればいいのに。

AppleがiPodを廃止したとき、誰も埋められない大きな隙間ができた。ここでの本当の変化はiPodが消えたことじゃないと思う。Spotifyやスマートフォンの存在がMP3プレーヤーを殺したんだ。それらが部屋の空気をたくさん占めてしまって、他のものを押しつぶしてしまったんだよ。

それはハードウェアやソフトウェアの問題じゃなくて、需要の問題だと思うよ。中国のメーカーがミニiPhone 16やミニS24みたいな、見た目も良くて音楽も聴けるスマホ機能を持ったデバイスを50〜100ドルで作ってるから、親たちは子供にMP3プレーヤーの代わりにそういうのを買うんじゃないかな。14歳の息子に電話を持たせないって、ちょっと変わった育て方だね。悪く言うつもりはないけど、今の市場にあるもの以上の需要を生むような人はあまりいないと思うよ。

Fiioはこのカテゴリーにたくさんの製品を出してるよ、例えばね。https://www.fiio.com/cp13 と https://www.fiio.com/jm21

そういえば、家のどこかにSanDisk Clipが転がってるのを思い出した。

ソニーは今でもすごく良いプレーヤーを作ってるよ、しかも「ウォークマン」ブランドでね。https://electronics.sony.com/audio/walkman-digital-recorders... たぶん10歳の子供には高すぎるかもしれないけど、中古をebayで見つけられるかも?

eBayでナゲットの袋を買えばいいじゃん :P

25年間FLAC形式で音楽コレクションを作ってきて、去年(Android)スマホと1TBのMicroSDカードを買ったんだ。これで全部の音楽が入るから、技術が追いつくのに長い時間がかかったけど、今はポケットに全部入るようになってすごく満足してるよ。ストリーミングサービスに頼りたくない人は他にもいるはずだし、広告や業界の押し付けから解放されたいよね。自分でアプリを作るために頑張ってる人もいるのを見ると、すごいなって思うよ。

Androidではカバーアートやタイトルが不安定な問題がずっとあって、変更しても変わらなかったり、変わったと思ったらランダムなカバーに戻ったりするんだ。これってAndroidのバグだと思うんだけど、君も遭遇したことある?

技術は何年も前に追いついてるんだよ。ただ、君が目的に合わないフォーマットにこだわってるだけ。良い再エンコードをすれば、音質は透明で(違いが聞き取れない)もっと小さいカードに全部の音楽を収められるよ。(バックアップとしてデスクトップにFLACを置いておくこともできるしね)

お前はすごいコレクションのキュレーターだな!俺のコレクションの約25%がFLAC/APE/ALAC/WavePackだけど、それでも3TB以上あるよ。これが移動中に音楽を聴くのを妨げてるんだ — 事前にモバイルデバイスに何を入れるか選べないからね :-)

俺もFLACだけの個人的なコレクションを作ってるよ、25年もかからずにね。もう1TB超えてるけど、サーバーは https://www.navidrome.org で、クライアントは https://symfonium.app がすごくいい感じ。今は2TBのSDカードもあるから、値段が下がったら買うつもり。

ちなみに、オフラインで音楽コレクションを持ってるなら、https://play.google.com/store/apps/details?id=in.krosbits.mu... をおすすめするよ。完璧に動作するから。

Symfoniumも素晴らしいよ(Plex、Jellyfin、WebDAV、SMBなどもサポートしてる)

これは結局意味がないね。革新的なテクノロジー企業が、民主的なアプリ開発に障害を設けるなんて。俺には理解できる。昔のディズニーCEO、マイケル・アイスナーのこの言葉を見てみて: > 我々にはアートを作る義務はない。歴史を作る義務もない。声明を出す義務もない。でもお金を稼ぐためには、歴史を作ったり、アートを作ったり、何か重要な声明を出すことがしばしば重要だ。アップルは本質的に革新的ではなく、民主的でもない。利益を追求するのが本質で、利益を上げるために革新や民主化を行う。だけど、入場料を払わずにアプリストアに無法者を入れるのは、金を稼ぐ良い方法じゃない。その料金こそが金の源なんだから。公共に金の卵を持ち逃げさせてるようなもんだ。