Le lecteur audio que j’ai créé moi-même
(nexo.sh)- En 2025 encore, lire librement de la musique MP3 sur iPhone reste très limité
- Les apps d’Apple et les apps tierces reposent pour la plupart sur des services payants ou offrent une ergonomie insuffisante
- L’app développée par l’auteur propose notamment une recherche plein texte, le support d’iCloud et une approche local-first
- Les approches cross-platform comme React Native ont montré leurs limites à cause des contraintes du système de fichiers et de problèmes de stabilité
- Avec SwiftUI et une architecture fondée sur SQLite, l’auteur a mis en place une expérience de gestion musicale indépendante et hautement extensible
Vue d’ensemble
Pour répondre lui-même à la frustration de ne toujours pas pouvoir lire librement sur iPhone, en 2025, des fichiers MP3 possédés par l’utilisateur, le développeur présente le processus et le résultat de la création de son propre lecteur audio. Alors que les services musicaux d’Apple comme les apps externes imposent diverses limitations et modèles payants, l’app qu’il a développée offre une expérience optimisée pour la gestion et la lecture des fichiers musicaux personnels.
Pourquoi avoir créé son propre lecteur audio
- Les fonctions de synchronisation cloud comme Apple Music et iCloud Music Library ne fonctionnent qu’avec un abonnement à un service payant
- Si l’abonnement est interrompu, la synchronisation automatique et l’accès au dossier musical sont entièrement bloqués
- Cela met en évidence l’absence de véritable contrôle du propriétaire sur l’intégration de sa bibliothèque musicale et l’usage polyvalent de ses appareils
- L’objectif était aussi de concrétiser une forme d’autodétermination : « sur un smartphone acheté, on peut aussi développer soi-même les fonctions vraiment nécessaires »
Analyse des solutions de lecture musicale d’Apple et des tiers
App native d’Apple
- L’app Files permet bien de lire des fichiers audio depuis un dossier iCloud, mais les fonctions de base comme la gestion des playlists, le tri par métadonnées ou la manipulation de la file d’attente sont insuffisantes
- L’expérience utilisateur n’est pas pensée pour l’écoute musicale
Apps tierces
- L’App Store propose diverses apps externes, mais beaucoup reposent sur un modèle d’abonnement, avec un niveau fonctionnel variable selon les apps
- Il existe aussi des apps payantes à achat unique comme Doppler, mais l’expérience de recherche et d’import dans de gros dossiers iCloud n’y est pas très fluide
Le parcours technique vers le « mode builder »
- L’auteur a décidé de créer lui-même son lecteur audio
- Les fonctionnalités visées : une recherche plein texte rapide sur l’ensemble des dossiers iCloud, des fonctions de gestion musicale de niveau app de musique officielle (file d’attente, playlists, tri, etc.) et une interface intuitive
Première tentative avec React Native
- En raison de certaines frustrations avec Swift (notamment avant le support d’async/await), React Native/Expo avait sa préférence
- L’implémentation de l’UI s’est plutôt bien passée grâce à des templates open source, mais il a rencontré des crashes et des limites fonctionnelles sur la gestion de l’accès au système de fichiers (dossiers iCloud) et de la synchronisation
- Il a fini par comprendre qu’avec la sandbox iOS, l’accès à des dossiers externes est impossible sans autorisation explicite, et a donc basculé vers Swift
Pourquoi le choix de SwiftUI
- Utilisation du paradigme d’UI déclarative de SwiftUI ainsi que du support moderne d’async/await et des Swift Actors
- Une séparation stricte entre UI et logique de données a permis de mettre en place un flux de données propre et une gestion de la concurrence au niveau métier
- Cela a aussi bien convenu à l’usage de LLM (OpenAI o1, DeepSeek, etc.), en limitant les dépendances dans le code UI généré
Architecture de l’app et modèle de données
-
SQLite est utilisé comme stockage de données, choisi à la place de CoreData car il permet d’exploiter directement la recherche plein texte (FTS5)
-
L’app repose sur 3 écrans/modes principaux :
- Import de bibliothèque : enregistrement en masse dans la base des chemins de fichiers audio par dossier iCloud, afin de faciliter recherche et gestion
- Gestion de la bibliothèque : playlists, classement des morceaux, édition, etc.
- Lecture musicale : gestion de la file d’attente (répétition, shuffle, etc.) et contrôles de base
-
Flux utilisateur lors de l’import de bibliothèque :
- Depuis un état initial vide, l’utilisateur sélectionne un dossier via « Add iCloud Source » et lance un scan de l’arborescence
- Une fois l’indexation terminée, il passe à l’onglet bibliothèque, avec listes par mots-clés et mini lecteur
- Lorsqu’un nouveau morceau est ajouté, il est fusionné automatiquement en arrière-plan
Couche logique de style backend
- Fort de son expérience de développement en startup web/cloud, l’auteur a séparé rigoureusement la logique métier de l’UI/ViewModel
- La couche domaine (Swift actors) porte les principales logiques métier (import, recherche, file d’attente, etc.) et garantit la sécurité des threads
- Les mises à jour de l’UI passent par le ViewModel, ce qui clarifie la découpe et réduit les dépendances entre synchronisation de fichiers, lecture et interface, améliorant ainsi la maintenabilité
Mise en place de la recherche plein texte avec SQLite
- À partir d’iOS 11, il est possible d’utiliser SQLite avec support FTS5 sans configuration particulière
- Cela permet une recherche rapide sans index de recherche externe ni serveur
- La bibliothèque SQLite.swift est utilisée pour les requêtes classiques, tandis que les requêtes FTS passent par du SQL écrit directement
Structure des tables FTS
songs_fts: indexation de artist, title, album, albumArtist, etc.source_paths_fts: indexation des chemins et noms de fichiers- Ces tables existent en parallèle des tables principales et sont utilisées dans l’UI uniquement pour la recherche (READ)
- Les mises à jour d’index sont gérées via des transactions DB pour préserver la cohérence des données
Recherche fuzzy et classement
- Un wildcard est ajouté automatiquement à la fin de la saisie, avec un tri par pertinence fondé sur BM25
- Au final, cela aboutit à une structure de données prévisible sans dépendance réseau et à un environnement de recherche locale puissant
Système de fichiers iOS et utilisation des bookmarks
- Contrairement à macOS, iOS ne prend pas en charge les security-scoped bookmarks, ce qui limite la persistance de l’accès étendu aux fichiers externes
- Seule l’information de chemin est conservée, et l’utilisateur doit réautoriser l’accès lors de chaque réouverture
- Solution adoptée : copier les fichiers eux-mêmes dans la sandbox de l’app au moment où l’accès est autorisé
- La copie automatique en arrière-plan améliore la vitesse d’indexation des fichiers
- Même après cela, il reste difficile de lire directement des fichiers externes après un redémarrage de l’appareil, ce qui montre à quel point les restrictions d’accès aux fichiers sur iOS sont sévères
Lecture avec AVFoundation et conception de l’interface
- Utilisation du framework AVFoundation et de AVURLAsset pour analyser les métadonnées des fichiers audio
- Certains champs comme le numéro de piste sont parsés manuellement (via les tags ID3)
- Pour la lecture audio, l’app utilise AVAudioPlayer et implémente MPRemoteCommandCenter ainsi que des protocoles Delegate pour l’intégration avec le centre de contrôle
Retour d’expérience et réflexion sur les politiques d’Apple
Points frustrants
- Environnement contraint de Xcode : les previews SwiftUI ont progressé, mais restent en retrait par rapport au confort de VSCode ou Flutter
- Manque de flexibilité de l’éditeur : utiliser Swift LSP dans Neovim ou VSCode demande des réglages supplémentaires et le résultat reste imparfait
- Certaines zones du SDK restent centrées sur Objective-C : notamment pour la recherche de métadonnées, avec peu d’API modernes vraiment adaptées à Swift
- Débogage iCloud fastidieux : impossible de reproduire complètement les fonctions cloud dans les previews SwiftUI, ce qui impose des mocks manuels
Points positifs
- Async/await rend nettement plus simple l’écriture de code concurrent orienté I/O
- Richesse des bibliothèques natives : cela permet de développer davantage de fonctionnalités en échappant aux limites des bindings open source
- Conception UI déclarative de SwiftUI : l’auteur y retrouve les points forts de l’approche React avec une forte productivité
Conclusion : le développement ne devrait-il pas être plus simple ?
- En 1,5 semaine de développement, l’objectif d’un lecteur musical local/hors ligne a été atteint
- En pratique, la distribution de l’app elle-même reste aussi limitée : sans certificat développeur, elle cesse de fonctionner au bout de 7 jours, et l’inscription développeur à 99 $ par an est nécessaire
- Même après le DMA Act de l’UE, le sideloading n’est toujours pas totalement ouvert, et les développeurs indépendants ou amateurs restent confrontés à des restrictions
- Les PWA sont elles aussi limitées sur iOS, avec l’absence de support de plusieurs API majeures (Web Bluetooth/USB/NFC, Background Sync, etc.)
- L’IA a abaissé les barrières au développement, mais iOS conserve une barrière d’entrée élevée à cause de règles artificielles
- Les limitations imposées aux développeurs indépendants et aux droits des utilisateurs persistent, et la fermeture d’iOS demeure un frein à l’innovation
1 commentaires
Avis sur Hacker News
asyncrend certes l’écriture plus pratique, mais à grande échelle, j’ai trouvé qu’il devenait bien plus difficile de suivre le flux du code et de raisonner sur la concurrence. Lorsqu’on se heurte à des problèmes non résolus, je pense qu’il existe des alternatives comme les green lightweight threads. À long terme, j’ai peur qu’une approche fondée sur async augmente au contraire les coûts de maintenance.