1 puntos por GN⁺ 2025-05-24 | 1 comentarios | Compartir por WhatsApp
  • Incluso en 2025, sigue habiendo muchas limitaciones para reproducir libremente música MP3 en el iPhone
  • La mayoría de las apps de Apple y de terceros son servicios de pago o tienen una experiencia de usuario deficiente
  • La app que hice ofrece búsqueda de texto completo, soporte para iCloud y un entorno local-first, entre otras cosas
  • Los enfoques multiplataforma como React Native tenían límites por las restricciones del sistema de archivos y problemas de estabilidad
  • Con SwiftUI y un diseño basado en SQLite, logré una experiencia de gestión musical independiente y altamente extensible

Resumen general

Para resolver por cuenta propia la molestia de que incluso en 2025 siga siendo difícil reproducir libremente archivos MP3 que el usuario posee en un iPhone, el desarrollador presenta el proceso y el resultado de haber creado su propia app de reproducción musical. Mientras que tanto los servicios musicales de Apple como las apps externas tienen varias restricciones y modelos de pago, la app hecha por él ofrece una experiencia optimizada para gestionar y reproducir archivos musicales del usuario.

Por qué decidió crear su propio reproductor de música

  • Las funciones de sincronización basadas en la nube, como Apple Music e iCloud Music Library, solo funcionan si se paga una suscripción
  • Si se cancela la suscripción, se bloquea por completo la sincronización automática y el acceso a la carpeta de música
  • Se hizo evidente la falta de derechos reales del propietario sobre la integración de la biblioteca musical existente y el uso general del dispositivo
  • Quería materializar la autodeterminación de que “si compraste un smartphone, también puedes crear por ti mismo las funciones que realmente necesitas”

Análisis de las soluciones de reproducción musical de Apple y terceros

App predeterminada de Apple

  • Es posible reproducir archivos de música desde una carpeta de iCloud usando la app Files, pero funciones básicas como gestión de playlists, ordenamiento por metadatos y manipulación de la cola son deficientes
  • Ofrece una experiencia de usuario no optimizada para escuchar música

Apps de terceros

  • En la App Store hay muchas apps externas, pero abundan los modelos de cobro por suscripción y el nivel funcional varía mucho entre apps
  • También existen apps de pago único como Doppler, pero la experiencia de búsqueda e importación en carpetas grandes de iCloud no resulta fluida

El recorrido técnico hacia el “modo builder”

  • Decidió que tenía que crear directamente su propia app de reproducción musical
  • Funciones requeridas: búsqueda rápida de texto completo sobre carpetas completas de iCloud, además de funciones de gestión musical al nivel de una app oficial de música (cola, playlists, ordenamiento, etc.) y una interfaz intuitiva

Primer intento con React Native

  • Debido a incomodidades previas con Swift (por ejemplo, antes no soportaba async/await), prefería React Native/Expo
  • Aunque la implementación de la UI fue razonable usando plantillas open source, encontró crashes y límites funcionales al manejar el acceso y la sincronización del sistema de archivos (carpetas de iCloud)
  • Al darse cuenta de que, por la política de sandbox de iOS, no era posible acceder a carpetas externas sin permisos explícitos, cambió a Swift

Por qué eligió SwiftUI

  • Aprovechó el paradigma declarativo de UI de SwiftUI, así como el soporte moderno de async/await y Swift Actor
  • Mediante una separación estricta entre UI y lógica de datos, implementó un flujo de datos limpio y manejo de concurrencia en el dominio
  • También ayudó a optimizar el uso de LLM (OpenAI o1, DeepSeek, etc.), contribuyendo a minimizar dependencias en el código de UI generado

Arquitectura de la app y modelo de datos

  • Usa SQLite como almacén de datos y lo eligió en lugar de CoreData porque permite usar directamente búsqueda de texto completo (FTS5)

  • Los 3 principales pantallas/modos de la app:

    1. Importación de biblioteca: guarda en lote en la DB las rutas de archivos de audio por carpeta de iCloud, para permitir búsqueda y gestión flexibles
    2. Gestión de biblioteca: playlists, clasificación de canciones, edición, etc.
    3. Reproducción musical: gestión de cola (repetir, shuffle, etc.) y controles básicos de canciones
  • Flujo del usuario al importar la biblioteca:

    • Desde un estado inicial vacío, selecciona una carpeta y escanea el árbol mediante "Add iCloud Source"
    • Cuando termina la indexación, pasa a la pestaña de biblioteca, donde hay listas por palabra clave y un mini reproductor
    • Si se agregan nuevas canciones, se fusionan automáticamente en segundo plano

Capa lógica estilo backend

  • Basándose en su experiencia desarrollando startups web/cloud, separó rigurosamente la capa lógica de la UI/ViewModel
  • La capa de dominio (Swift actors) contiene la lógica principal de negocio (importación, búsqueda, cola, etc.) y asegura la seguridad de hilos
  • Las actualizaciones de UI se dividen limpiamente a través del ViewModel, mejorando el mantenimiento al minimizar dependencias entre sincronización de archivos, reproducción y UI

Implementación de búsqueda de texto completo con SQLite

  • Desde iOS 11 en adelante se puede usar SQLite con soporte FTS5 sin configuración adicional
  • Ofrece búsqueda rápida sin necesidad de índices o servidores externos
  • Usa la librería SQLite.swift para consultas generales y sentencias SQL directas para consultas FTS

Estructura de tablas FTS

  • songs_fts: indexa artist, title, album, albumArtist, etc. de las canciones
  • source_paths_fts: indexa rutas de archivos y nombres de archivo
  • Existen en paralelo con las tablas principales y en la UI se usan solo para búsqueda (READ)
  • La actualización de índices se maneja con transacciones de DB para mantener la consistencia de los datos

Búsqueda difusa y ranking

  • Agrega automáticamente un wildcard al final de la entrada y ordena por relevancia basada en BM25
  • En conjunto, se logra una estructura de datos predecible sin dependencia de red y un potente entorno de búsqueda local

Uso del sistema de archivos de iOS y Bookmarks

  • A diferencia de macOS, iOS no soporta security-scoped bookmarks, por lo que carece de persistencia sólida para ampliar el acceso a archivos externos
  • Como solo se guarda la información de la ruta, cuando se vuelve a acceder el usuario debe aprobar otra vez el permiso
  • Solución: en el momento en que se concede acceso, guardar una copia del archivo dentro del sandbox de la app
  • La copia automática en segundo plano mejora la velocidad de indexación de archivos
  • Incluso después de reiniciar el dispositivo sigue siendo difícil reproducir directamente archivos externos, lo que muestra lo severas que son las restricciones de acceso a archivos en iOS

Reproducción con AVFoundation y diseño de interfaz

  • Usa el framework AVFoundation y AVURLAsset para analizar metadatos de archivos de audio
  • Algunos campos, como el número de pista, se parsean manualmente usando etiquetas ID3
  • Para la reproducción de audio usa AVAudioPlayer, e implementa MPRemoteCommandCenter y protocolos Delegate para integrarse con el Centro de control

Reflexiones tras el desarrollo y sobre las políticas de Apple

Aspectos incómodos

  • Entorno restrictivo de Xcode: aunque las vistas previas en tiempo real de SwiftUI han mejorado, no alcanzan la comodidad de VSCode o Flutter
  • Poca flexibilidad del editor: para usar Swift LSP en Neovim o VSCode se necesita configuración adicional y el acabado sigue siendo limitado
  • Algunas zonas del SDK siguen centradas en Objective-C: faltan APIs modernas realmente amigables con Swift para tareas como búsqueda de metadatos
  • Depurar la integración con iCloud es engorroso: en las vistas previas de SwiftUI no se pueden implementar completamente las funciones cloud y hay que armar mocks manualmente

Aspectos positivos

  • Con async/await, escribir código de concurrencia orientado a I/O se volvió notablemente más fácil
  • Ricas librerías nativas: permite desarrollar funciones más variadas al salir de las limitaciones de los bindings open source
  • Diseño declarativo de UI en SwiftUI: se perciben tanto las fortalezas del enfoque tipo React como una alta productividad

Conclusión: ¿no debería ser más fácil desarrollar?

  • En 1.5 semanas logró el objetivo de un reproductor de música local/offline
  • En la práctica, incluso la distribución de la propia app tiene restricciones: sin certificado de desarrollador deja de funcionar a los 7 días, y se requiere el registro anual de desarrollador de $99
  • Incluso después de la EU DMA Act, el sideloading no está completamente abierto, y las restricciones siguen para desarrolladores individuales o de hobby
  • Las PWA también siguen limitadas en iOS por la falta de soporte de APIs importantes (Web Bluetooth/USB/NFC, Background Sync, etc.)
  • Aunque la IA ha bajado la barrera de desarrollo, iOS mantiene una barrera de entrada alta por regulaciones artificiales
  • Las limitaciones a los desarrolladores independientes y a los derechos del usuario siguen presentes, y el carácter cerrado de iOS continúa siendo un obstáculo para la innovación

1 comentarios

 
GN⁺ 2025-05-24
Comentarios de Hacker News
  • Llevo 25 años construyendo mi colección musical en formato FLAC, y el año pasado compré un teléfono Android y una tarjeta MicroSD de 1 TB, así que me dio una gran satisfacción poder llevar toda mi música en el bolsillo. Seguro no soy la única persona que no quiere rentar música, perder el control, hacer streaming de lo que la industria empuja ni lidiar con anuncios. Se siente genial ver casos de gente desarrollando su propia aplicación.
    • La tecnología ya estaba más que lista desde hace años; el problema es que yo sigo aferrado a un formato que no me conviene. Con una buena recodificación puedes guardar toda tu música en mucho menos espacio con una calidad tan transparente que no notarías la diferencia. Recomiendo dejar los archivos FLAC en la desktop como respaldo.
    • Qué bien coleccionas de verdad. En mi caso, como 25% de mi colección está en formatos sin pérdida como FLAC/APE/ALAC/WavePack y ya pasa de 3 TB. Por eso me cuesta escuchar música cuando voy en movimiento: me resulta difícil decidir de antemano qué música pasar al dispositivo móvil.
    • En Android sigo teniendo problemas con portadas de álbumes o información de títulos que no se reflejan bien o cambian aleatoriamente. Me parece un bug de Android; me pregunto si alguien ha logrado resolverlo.
    • Yo también tengo una colección personal solo en FLAC, aunque todavía no llego a 25 años. Ya pasé de 1 TB, y estoy muy satisfecho usando el servidor Navidrome y el cliente Symfonium. Ya empezaron a salir tarjetas microSD de 2 TB, así que probablemente compre una cuando baje más de precio.
  • Escucho música desde la época de winamp, y aun en la era del streaming sigo usando una biblioteca musical local organizada por carpetas. Igual que otros en los comentarios, yo también hice por hobby un reproductor de música old school para escuchar música offline. Es una app de html/js de una sola página, con control total por teclado y una función sencilla de cola (playlist). Recomiendo echarle un vistazo: https://nobsutils.com/mp
    • Yo también soy de los que piensa que la UI de winamp era realmente excelente, incluso 27 años después. La gran fortaleza era esa simplicidad de tener colecciones de archivos por carpeta, reproducción aleatoria total y la opción de reproducir solo un directorio específico.
    • Tu app hecha por ti mismo realmente funciona muy bien.
    • Para mí, foobar2000 era mi reproductor de música favorito; ahora lo he reemplazado con la app Cog.
  • Yo desarrollé mi propia webapp para escuchar álbumes completos y poder seguir exactamente donde me quedé aunque cambie de dispositivo. Me gusta escuchar los álbumes de principio a fin, pero con servicios como YouTube Music me ha pasado que no recuerdan bien la posición de reproducción o que cambiar de dispositivo es incómodo. En la webapp que hice, basta con pegar una URL para que se descargue al servidor con yt-dlp y desde ahí se pueda hacer streaming. Siempre recuerda la posición de reproducción, así que puedo seguir en mi laptop del trabajo exactamente donde me quedé escuchando en el auto. También funciona increíblemente bien para agregar mixes de otras fuentes como NTS Radio.
    • Totalmente de acuerdo con que YouTube Music no guarda la cola ni permite cambiar de dispositivo de forma fluida. Me gustaría probar alguna vez la webapp que hiciste.
  • Ojalá el artículo hubiera hablado no solo del dispositivo físico, sino también del software para administrarlo y reproducirlo. Hace unos años quise comprarle un reproductor mp3 a mi hijo de 10 años y me sorprendió ver que casi no había productos adecuados. Apple dejó un gran vacío en el mercado al descontinuar el iPod, pero todavía nadie lo ha llenado de verdad. El iPod shuffle (en forma de memoria USB) fue el mejor reproductor mp3 que he usado: era pequeño, se conectaba directo y la batería duraba mucho. Incluso el concepto de funcionar solo con shuffle y sin pantalla era más bien una ventaja. Hoy el mercado de hardware ya no replica ni siquiera ese tipo de dispositivo simple. Algunos lo atribuyen a problemas de software/DRM, pero a mí me da pena; me gustaría que existiera un dispositivo barato, portátil y dedicado solo a reproducir música.
    • Creo que el principal cambio no fue la desaparición del iPod, sino la masificación de Spotify y los smartphones. Entre ambos se comieron casi todo el mercado y desplazaron cualquier otra opción.
    • Fiio sí está sacando varios productos de esa categoría. ejemplo1 ejemplo2
    • No creo que sea un problema de hardware ni de software, sino de demanda. Fabricantes chinos están vendiendo mini dispositivos tipo Mini iPhone 16 o Mini S24, con funciones de smartphone y reproducción musical, por $50~$100. Lo más probable es que la mayoría de los padres compre eso a sus hijos antes que un reproductor mp3, y tampoco hay tantos padres dispuestos a no darles un teléfono hasta los 14 años; así se forma la demanda del mercado.
    • Sony todavía sigue sacando buenos reproductores bajo la marca "walkman". enlace oficial Para un niño de 10 años quizá sean un poco caros, así que recomendaría buscar uno usado en eBay.
    • Esto me hizo recordar con nostalgia aquellos reproductores mp3 como el SanDisk Clip que probablemente todavía tengo tirado en alguna parte de la casa.
  • Me gustó leer este artículo y todavía no lo termino. Disfruté mucho la parte de leer cómo el desarrollador va tomando decisiones pequeñas y detalladas, y el trasfondo de esas decisiones. En casi todas las apps de música, la UX y el layout se ven parecidos, así que siempre siento que estoy "boxeando" con todas ellas. Ánimo a quienes se atreven a intentar algo distinto.
  • Yo sigo usando solo archivos locales en la app Apple Music. Tengo desactivado el servicio de streaming de Apple Music, cargo toda mi música en la app Apple Music de macOS y luego conecto el teléfono a la laptop para sincronizarlo como si fuera 2007. Como mi música no cambia mucho, este método no me causa problemas, y además me da cierta nostalgia esa sincronización por cable.
    • También vale mencionar que la sincronización automática por wi-fi con iTunes sigue funcionando bien.
  • Sobre la pregunta de "por qué una empresa de TI innovadora pone obstáculos al desarrollo democrático de aplicaciones", citaría a Michael Eisner, ex CEO de Disney: al final, la naturaleza de una empresa es perseguir ganancias. Apple no es una empresa innovadora ni democrática, sino una empresa orientada a maximizar ingresos. A menos que garantice más ganancias, reducir las barreras de entrada para desarrolladores o abrir más democráticamente significaría renunciar a la gallina de los huevos de oro que es la tienda oficial. En otras palabras, la lógica de priorizar la ganancia es lo que manda.
  • Para usuarios de Android que tienen una biblioteca musical offline, recomiendo mucho Musicolet. Funciona perfecto.
    • Symfonium también es excelente por su soporte amplio para Plex, Jellyfin, WebDAV, SMB y más.
  • Disfruté mucho el análisis técnico en profundidad, y al pasar de React Native a SwiftUI se nota cuánto más fácil se vuelve el código nativo para acceso a iCloud y optimización. También me impresionaron los trucos de búsqueda con SQLite FTS5, y pienso tomar ideas para mi app de biblioteca.
  • Al principio evité Swift porque me parecía difícil, pero no estoy de acuerdo con la idea de que la llegada de async/await haya facilitado escribir código concurrente. async sí da comodidad para escribir código, pero cuando el sistema crece, mi experiencia es que se vuelve mucho más difícil seguir el flujo del código y entender la concurrencia. Cuando hay problemas sin resolver, creo que existen alternativas como green lightweight threads. A largo plazo, me preocupa que el enfoque basado en async termine elevando el costo de mantenimiento.
    • Creo que el problema no es tanto el concepto de concurrencia en sí, sino más bien los límites de la abstracción async/await. Una buena concurrencia debería hacer que, al escalar el código, sea más fácil de entender y de mantener, y me parece que la encapsulación centrada en procesos/servicios ofrece grandes ventajas.
    • Para el objetivo de un reproductor de música simple, de todos modos parece poco probable que el aumento de complejidad por usar async llegue a ser un problema importante.