1 points par GN⁺ 2025-05-24 | 1 commentaires | Partager sur WhatsApp
  • 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 :

    1. Import de bibliothèque : enregistrement en masse dans la base des chemins de fichiers audio par dossier iCloud, afin de faciliter recherche et gestion
    2. Gestion de la bibliothèque : playlists, classement des morceaux, édition, etc.
    3. 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

 
GN⁺ 2025-05-24
Avis sur Hacker News
  • J’ai construit ma collection musicale au format FLAC pendant 25 ans, et l’an dernier j’ai acheté un téléphone Android avec une carte MicroSD de 1 To : je suis ravi de pouvoir avoir toute ma musique dans ma poche. Je me dis que je ne suis sûrement pas le seul à ne pas vouloir louer sa musique, perdre le contrôle, streamer les morceaux poussés par l’industrie ou subir la publicité. C’est vraiment cool de voir quelqu’un développer sa propre application.
    • À mon avis, la technologie est à la hauteur depuis déjà plusieurs années, c’est juste que je m’obstine à utiliser un format qui ne me convient pas. Avec un bon réencodage, on peut stocker toute sa musique dans beaucoup moins d’espace avec une qualité suffisamment transparente pour ne pas entendre la différence. Je recommande de garder les fichiers FLAC sur un desktop pour les sauvegardes.
    • Bravo, là on a affaire à quelqu’un qui collectionne vraiment sérieusement. Dans mon cas, environ 25 % de ma collection est en formats sans perte comme FLAC/APE/ALAC/WavePack, et ça dépasse les 3 To. C’est pour ça qu’écouter de la musique en déplacement reste compliqué : difficile de choisir à l’avance quoi transférer sur un appareil mobile.
    • Sur Android, je rencontre sans arrêt des problèmes où les pochettes d’album ou les titres ne s’affichent pas correctement, ou changent aléatoirement. Ça ressemble à un bug Android ; je me demande si quelqu’un a déjà trouvé une solution.
    • Moi aussi, je constitue ma collection personnelle uniquement en FLAC, même si ça ne fait pas encore 25 ans. J’ai dépassé 1 To, et je suis très satisfait de ma combinaison serveur Navidrome + client Symfonium. Des cartes microSD de 2 To commencent à arriver, donc je m’en prendrai probablement une quand les prix baisseront davantage.
  • J’écoute de la musique depuis l’époque de winamp, et même à l’ère du streaming, j’utilise encore une bibliothèque musicale locale organisée par dossiers. Comme d’autres commentateurs ici, j’ai aussi créé pour le plaisir un lecteur de musique old school pour l’écoute hors ligne. C’est une appli html/js d’une seule page, avec contrôle complet au clavier et une fonction simple de file d’attente (playlist). Je recommande d’aller voir https://nobsutils.com/mp.
    • Moi aussi, je pense depuis 27 ans que l’interface de winamp était vraiment excellente. Sa grande force, c’était la simplicité : une collection de fichiers rangés par dossiers, lecture aléatoire sur l’ensemble, ou lecture d’un répertoire précis uniquement.
    • Retour d’expérience : l’application maison fonctionne vraiment très bien.
    • Pour moi, foobar2000 a longtemps été mon lecteur audio préféré. Aujourd’hui, je l’ai remplacé par l’application Cog.
  • J’ai développé moi-même une web app qui me permet d’écouter des albums entiers et de reprendre exactement là où je m’étais arrêté quand je change d’appareil. J’aime écouter les albums du début à la fin, mais des services comme YouTube Music gèrent mal la mémorisation de la position de lecture ou rendent le passage d’un appareil à l’autre pénible. Dans ma web app, il suffit de coller une URL pour que le serveur télécharge le contenu via yt-dlp, puis le diffuse en streaming. Elle mémorise toujours la position de lecture, ce qui me permet de reprendre au bureau sur mon laptop exactement là où j’en étais en voiture. Ça marche aussi remarquablement bien avec des mix provenant d’autres sources comme NTS Radio.
    • Je partage totalement la frustration concernant l’absence de sauvegarde de la file d’attente et la transition peu fluide entre appareils dans YouTube Music. J’aimerais vraiment pouvoir essayer la web app développée par l’auteur.
  • J’aurais aimé que l’article parle non seulement des appareils physiques, mais aussi des logiciels qui servent à les gérer et à lire la musique. Il y a quelques années, je voulais acheter un lecteur mp3 à mon fils de 10 ans, et j’ai été choqué de constater qu’il n’existait presque aucun produit adapté. Apple a laissé un énorme vide en arrêtant l’iPod, mais personne ne l’a vraiment comblé depuis. L’iPod shuffle (au format clé USB) reste le meilleur lecteur mp3 que j’aie utilisé : petit, facile à brancher, avec une excellente autonomie. L’absence d’écran et le mode shuffle uniquement étaient même plutôt un avantage. Ce genre d’appareil simple n’existe plus aujourd’hui sur le marché hardware. Certains y verront un problème de logiciel ou de DRM, mais je trouve ça dommage et j’aimerais qu’il existe encore des appareils bon marché et très portables qui ne servent qu’à lire de la musique.
    • Je pense que le changement principal ne vient pas de la disparition de l’iPod, mais de la généralisation de Spotify et des smartphones. À eux deux, ils ont accaparé l’essentiel du marché et évincé quasiment toutes les autres options.
    • Fiio propose plusieurs produits dans cette catégorie. Exemple 1 Exemple 2
    • À mon avis, le problème n’est ni matériel ni logiciel, mais simplement la demande. Des fabricants chinois vendent déjà pour 50 à 100 $ des mini-appareils qui ressemblent à des Mini iPhone 16 ou Mini S24, avec des fonctions de smartphone et la lecture musicale. La plupart des parents ont plus de chances d’acheter ce type d’appareil à leurs enfants qu’un lecteur mp3, et peu attendent l’âge de 14 ans avant de leur donner un téléphone. La demande du marché s’est donc structurée en conséquence.
    • Sony continue encore aujourd’hui à sortir de bons lecteurs sous la marque "walkman". Lien officiel Cela peut être un peu cher pour un enfant de 10 ans, donc je recommanderais plutôt de chercher en occasion sur eBay.
    • Ce commentaire m’a rappelé avec nostalgie qu’il doit bien y avoir quelque part dans la maison un lecteur mp3 du type SanDisk Clip.
  • J’ai lu ce billet avec plaisir, même si je ne l’ai pas encore terminé. J’ai particulièrement aimé suivre les petites décisions minutieuses prises par le développeur et comprendre leur contexte. Presque toutes les apps musicales ont l’air d’avoir la même UX et la même mise en page, et j’ai toujours l’impression de devoir « boxer » avec elles. Courage à ceux qui tentent de nouvelles approches.
  • J’utilise toujours uniquement des fichiers locaux dans l’application Apple Music. J’ai désactivé le service de streaming Apple Music, chargé toute ma musique dans l’app Apple Music sur macOS, puis je branche mon téléphone à mon laptop pour synchroniser comme en 2007. Comme ma collection ne change pas souvent, cette méthode me convient très bien, et elle me donne en plus une certaine nostalgie de la synchronisation filaire.
    • La synchronisation automatique en wi-fi via iTunes fonctionne d’ailleurs toujours très bien.
  • À propos de la question « pourquoi une entreprise informatique innovante met-elle plutôt des obstacles au développement d’applications démocratiques ? », on peut citer l’ancien PDG de Disney, Michael Eisner : au final, la nature d’une entreprise est de rechercher le profit. Apple n’est pas une entreprise innovante ou démocratique, mais une entreprise tournée vers la rentabilité. À moins qu’un assouplissement des barrières à l’entrée ou une ouverture plus démocratique ne garantisse davantage de revenus, cela reviendrait à renoncer à la poule aux œufs d’or que représente la boutique officielle. En clair, la logique du profit passe avant tout.
  • Pour les utilisateurs Android qui possèdent une bibliothèque musicale hors ligne, je recommande très vivement Musicolet. Ça fonctionne parfaitement.
    • Symfonium est aussi excellent, avec une prise en charge très large de Plex, Jellyfin, WebDAV, SMB, etc.
  • J’ai beaucoup apprécié cette analyse technique approfondie. En passant de React Native à SwiftUI, j’ai vraiment ressenti à quel point le code natif simplifie l’accès à iCloud et l’optimisation. Les astuces de recherche SQLite FTS5 m’ont aussi impressionné, et je pense m’en inspirer pour mon application de bibliothèque.
  • J’évitais Swift au début parce que je le trouvais difficile, mais je ne suis pas d’accord avec l’idée que l’ajout de async/await a rendu l’écriture du code concurrent plus simple. async rend 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.
    • À mon avis, le vrai problème vient moins du concept de concurrence lui-même que des limites de l’abstraction async/await. Une bonne concurrence devrait rendre le code plus compréhensible et plus facile à gérer à mesure qu’il grandit, et l’encapsulation centrée sur les processus/services apporte de gros avantages.
    • Pour un lecteur de musique simple comme le sien, cela dit, la complexité supplémentaire induite par async ne sera probablement presque jamais un vrai problème.