मैंने खुद बनाया हुआ ऑडियो प्लेयर
(nexo.sh)- 2025 में भी iPhone पर MP3 संगीत को आज़ादी से चलाने पर कई सीमाएँ हैं
- Apple और third-party apps ज़्यादातर paid services हैं या user convenience के मामले में कमज़ोर हैं
- खुद बनाए गए app में full-text search, iCloud support, local-first environment जैसी सुविधाएँ हैं
- React Native जैसी cross-platform approach में file system restrictions और stability issues की वजह से सीमाएँ थीं
- SwiftUI और SQLite-आधारित design के साथ स्वतंत्र और highly extensible music management अनुभव बनाया गया
अवलोकन
2025 में भी iPhone पर उपयोगकर्ता के अपने MP3 files को स्वतंत्र रूप से चलाना मुश्किल है। इसी असुविधा को सीधे हल करने के लिए डेवलपर ने खुद एक music player app बनाया, और यह लेख उसी प्रक्रिया और उसके परिणाम को बताता है। Apple की music services और बाहरी apps, दोनों में तरह-तरह की सीमाएँ और paid models हैं, जबकि खुद बनाए गए app में user music files के management और playback के लिए optimized experience दिया गया है।
खुद music player बनाने की वजह
- Apple Music और iCloud Music Library जैसे cloud-based sync features केवल paid subscription services में काम करते हैं
- subscription बंद होते ही automatic sync और music folders access पूरी तरह बंद हो जाता है
- मौजूदा music library integration और general device usability में owner rights की कमी महसूस हुई
- "जो feature मेरे लिए ज़रूरी है, उसे खरीदे गए smartphone पर मैं खुद भी बना सकता हूँ" — इस self-determination को साकार करना उद्देश्य था
Apple और third-party music playback solutions का विश्लेषण
Apple का default app
- Files app से iCloud folder के music files चलाए जा सकते हैं, लेकिन playlist management, metadata sorting, queue handling जैसी बुनियादी सुविधाएँ बहुत कमज़ोर हैं
- यह music listening के लिए optimized user experience नहीं देता
Third-party apps
- App Store में कई बाहरी apps हैं, लेकिन उनमें subscription-based billing models बहुत आम हैं और हर app का feature level अलग है
- Doppler जैसे कुछ paid one-time purchase apps भी हैं, लेकिन बड़े iCloud folders में search और import experience पर्याप्त रूप से smooth नहीं है
“Builder mode” की ओर तकनीकी यात्रा
- खुद music player app बनाने का फैसला किया गया
- ज़रूरी features: पूरे iCloud folder पर fast full-text search, official music app के स्तर के music management features (queue, playlist, sorting आदि) और intuitive interface
React Native के साथ पहली कोशिश
- Swift के पिछले अनुभव में असुविधा (जैसे पहले async/await का support न होना) की वजह से React Native/Expo को प्राथमिकता दी गई
- open source templates की मदद से UI बनाना आसान रहा, लेकिन file system (iCloud folder) access और sync handling में app crashes और functional limitations सामने आईं
- iOS sandbox policy के कारण explicit permission के बिना external folders access नहीं किया जा सकता — यह समझ आने पर Swift पर switch किया गया
SwiftUI चुनने की वजह
- SwiftUI के declarative UI paradigm, modern async/await, और Swift Actor support का उपयोग किया गया
- UI और data logic को सख्ती से अलग रखकर साफ data flow और domain concurrency handling लागू की गई
- LLMs (OpenAI o1, DeepSeek आदि) के उपयोग को optimize करने में मदद मिली, और generated UI code की dependencies भी कम रहीं
App architecture और data model
-
data store के रूप में SQLite का उपयोग किया गया; full-text search (FTS5) तुरंत उपलब्ध होने के कारण CoreData की जगह इसे चुना गया
-
app के 3 मुख्य screens/modes:
- Library import: iCloud folders के audio file paths को bulk में DB में store करना, ताकि flexible search/management हो सके
- Library management: playlists, song categorization, editing आदि
- Music playback: queue management (repeat, shuffle आदि) और बुनियादी song controls
-
library import के दौरान user flow:
- शुरुआती empty state में "Add iCloud Source" से folder चुना जाता है और tree scan किया जाता है
- indexing पूरी होने पर library tab में ले जाया जाता है, जहाँ keyword-based lists और mini player मिलता है
- नए songs जुड़ने पर वे background में automatically merge हो जाते हैं
Backend-style logic layer
- web/cloud startup development experience के आधार पर logic layer और UI/ViewModel को सख्ती से अलग किया गया
- domain layer (Swift actors) में मुख्य business logic (import, search, queue आदि) रखा गया, जिससे thread safety सुनिश्चित हुई
- UI updates को ViewModel के माध्यम से साफ तौर पर विभाजित किया गया, जिससे file sync, playback और UI के बीच dependencies कम हुईं और maintainability बेहतर हुई
SQLite के साथ full-text search लागू करना
- iOS 11 और उसके बाद से बिना अलग configuration के FTS5-supported SQLite इस्तेमाल किया जा सकता है
- बाहरी search index या server के बिना fast search उपलब्ध है
- सामान्य queries के लिए SQLite.swift library का उपयोग किया गया, जबकि FTS queries के लिए direct SQL statements लिखे गए
FTS table structure
songs_fts: songs के artist, title, album, albumArtist आदि को index करता हैsource_paths_fts: file paths और file names को index करता है- ये main tables के साथ-साथ मौजूद रहते हैं और UI में केवल search (READ) purpose के लिए इस्तेमाल होते हैं
- index updates DB transactions से किए जाते हैं ताकि data consistency बनी रहे
Fuzzy search और ranking
- input value के अंत में wildcard अपने-आप जोड़ा जाता है, और BM25-आधारित relevance order में sorting होती है
- कुल मिलाकर, network dependency के बिना predictable data structure और शक्तिशाली local search environment हासिल किया गया
iOS file system और bookmarks का उपयोग
- macOS के विपरीत iOS में security-scoped bookmarks support नहीं है, इसलिए external file access persistence कमज़ोर है
- सिर्फ path information store होती है, इसलिए दोबारा access पर user को permission फिर से देनी पड़ती है
- समाधान: access की अनुमति मिलने पर file को app sandbox में copy करके store किया गया
- background में automatic copy के ज़रिए file indexing speed बेहतर हुई
- device reboot के बाद external files को सीधे चलाना अब भी कठिन है, और इससे iOS की file access restrictions की गंभीरता साफ दिखती है
AVFoundation-आधारित playback और interface design
- audio file metadata analysis के लिए AVFoundation framework और AVURLAsset का उपयोग किया गया
- track number जैसे कुछ fields को manually parse किया गया (ID3 tags का उपयोग करके)
- audio playback के लिए AVAudioPlayer इस्तेमाल किया गया, और Control Center integration के लिए MPRemoteCommandCenter और Delegate protocols लागू किए गए
विकास के बाद के विचार और Apple policies पर नजर
क्या असुविधाजनक रहा
- Xcode का restrictive environment: SwiftUI live preview में सुधार हुआ है, लेकिन VSCode या Flutter जैसी सुविधा अभी नहीं मिलती
- editor flexibility की कमी: Neovim या VSCode में Swift LSP इस्तेमाल करने के लिए अतिरिक्त setup चाहिए और वह भी पूरी तरह polished नहीं है
- SDK के कुछ हिस्से अब भी Objective-C केंद्रित हैं: metadata search जैसी जगहों पर modern Swift-friendly APIs की कमी महसूस हुई
- iCloud integration debugging झंझटभरी है: SwiftUI preview में cloud features पूरी तरह लागू नहीं किए जा सकते, इसलिए direct mock setup बनाना पड़ता है
क्या अच्छा लगा
- Async/await की मदद से I/O-bound concurrency code लिखना काफ़ी आसान हो गया
- समृद्ध native libraries: open source bindings की सीमाओं से बाहर निकलकर ज्यादा विविध features बनाए जा सकते हैं
- SwiftUI का declarative UI design: React-style strengths और high productivity दोनों का अनुभव मिला
निष्कर्ष: क्या development और आसान नहीं होना चाहिए?
- 1.5 हफ्ते के development में local/offline music player का लक्ष्य हासिल कर लिया गया
- व्यवहार में app distribution पर भी restrictions हैं: developer certificate के बिना 7 दिन बाद app चलना बंद हो जाता है, और सालाना $99 developer registration चाहिए
- EU DMA Act के बाद भी sideloading पूरी तरह खुला नहीं है, इसलिए व्यक्तिगत और hobby developers के लिए सीमाएँ बनी हुई हैं
- PWAs भी iOS पर सीमित हैं: कई प्रमुख APIs supported नहीं हैं (Web Bluetooth/USB/NFC, Background Sync आदि)
- AI ने development barriers कम किए हैं, लेकिन iOS अब भी artificial rules की वजह से entry barrier ऊँचा रखता है
- independent developers और user rights पर restrictions अब भी कायम हैं, और iOS की closed nature आज भी innovation में बाधा है
1 टिप्पणियां
Hacker News राय
yt-dlpसे server पर डाउनलोड हो जाता है और वहीं से stream किया जा सकता है, यह हमेशा playback position याद रखता है, इसलिए कार में जहाँ सुनना छोड़ा था वहीं से ऑफिस के laptop पर जारी रख सकता हूँ, और NTS Radio जैसे दूसरे source mix जोड़ना भी बहुत बढ़िया काम करता हैasync/awaitजुड़ने से concurrency code लिखना आसान हो गया — इस दावे से मैं सहमत नहीं हूँ,asyncलिखते समय सुविधा देता है, लेकिन system बड़ा होने पर code flow और concurrency को समझना कहीं ज़्यादा मुश्किल हो जाता है, जब समस्या अनसुलझी हो तो green lightweight threads जैसे विकल्प बेहतर लगते हैं, और लंबे समय में async-आधारित तरीका maintenance cost बढ़ा सकता है, यह चिंता हैasync/awaitabstraction की सीमाओं में ज़्यादा है, अच्छी concurrency ऐसी होनी चाहिए कि code scale होने पर उसे समझना और manage करना आसान हो, और process/service-केंद्रित encapsulation यहाँ बड़ा लाभ देता है