
專案概述
Muon 是一款簡約、無廣告的 iOS/Android 行動音樂播放器,可串流和下載 YouTube 內容。用戶可搜尋 YouTube、在背景播放音樂(含鎖定螢幕控制)、下載音頻(m4a)或完整影片(H.264/mp4),並管理離線播放清單。FastAPI 後端透過任務佇列非同步處理下載任務,支援狀態輪詢,並自動清理過期磁碟檔案。
技術挑戰與解決方案
iOS & Android 背景音頻播放
當 App 進入背景或畫面鎖定時,需要在兩個平台上維持不間斷的音頻播放。
解決方案:
整合 audio_service 將 App 註冊為背景音頻服務,實作所需的平台回呼(播放/暫停/跳過)。結合 just_audio 處理實際播放,實現原生鎖定螢幕控制和藍牙耳機支援。
非同步下載任務系統
透過 yt-dlp 下載 YouTube 內容可能需要 10–60 秒以上。同步 API 會超時並讓客戶端無回應。
解決方案:
在 FastAPI 後端實作非同步任務佇列:POST /api/download 端點立即返回 task_id,Flutter 客戶端輪詢 GET /api/status/ 直到狀態為「completed」,再取得媒體 URL。
離線儲存與播放清單管理
需要在裝置本地 SQLite 資料庫中可靠地管理下載曲目和用戶播放清單。
解決方案:
使用 Drift(Flutter 的型別安全 SQLite ORM,含程式碼生成)定義曲目和播放清單的強型別表格,確保安全的資料庫遷移和編譯期查詢正確性。
系統架構
Flutter 前端:Riverpod(程式碼生成)管理狀態、just_audio + audio_service 實現背景播放、Drift(SQLite)本地離線儲存、Dio 處理 HTTP 請求。FastAPI 後端:yt-dlp + ffmpeg 非同步任務系統、/api/status/ 輪詢端點、StaticFiles 提供媒體存取。使用 Docker Compose 部署。
學習與心得
開發 Muon 讓我深入了解 Flutter 音訊生態(just_audio、audio_service)以及 iOS/Android 背景媒體播放的複雜性。在 FastAPI 上設計帶狀態輪詢的非同步任務佇列,是處理長時間執行任務而不阻塞 API 的寶貴模式。
技術棧
行動框架
FlutterDartRiverpod
音訊與播放
just_audioaudio_servicevideo_player
本地資料庫
Drift (SQLite)
後端
PythonFastAPI
媒體處理
yt-dlpffmpeg
部署
Docker Compose