1 pontos por GN⁺ 2025-05-24 | 1 comentários | Compartilhar no WhatsApp
  • Mesmo em 2025, ainda há muitas restrições para reproduzir livremente músicas em MP3 no iPhone
  • Os apps da Apple e de terceiros em sua maioria exigem pagamento ou deixam a desejar em usabilidade
  • O app feito pelo próprio autor oferece busca full-text, suporte ao iCloud e um ambiente local-first
  • Abordagens cross-platform como React Native tinham limitações por restrições do sistema de arquivos e problemas de estabilidade
  • Com SwiftUI e uma arquitetura baseada em SQLite, foi possível criar uma experiência de gerenciamento de música independente e altamente expansível

Visão geral

Para resolver por conta própria o incômodo de ainda ser difícil, mesmo em 2025, reproduzir livremente no iPhone arquivos MP3 que o próprio usuário possui, o desenvolvedor apresenta o processo e o resultado de criar ele mesmo um app de player de música. Enquanto os serviços musicais da Apple e os apps externos impõem diversas restrições e modelos pagos, o app implementado diretamente oferece uma experiência otimizada para gerenciar e reproduzir arquivos musicais do usuário.

Por que criar um player de música por conta própria

  • Recursos de sincronização em nuvem como Apple Music e iCloud Music Library só funcionam mediante assinatura de serviços pagos
  • Ao cancelar a assinatura, a sincronização automática e o acesso à pasta de músicas ficam totalmente bloqueados
  • Isso levou à percepção da falta de direito de propriedade efetivo sobre a integração da biblioteca musical existente e o uso geral do dispositivo
  • A ideia era concretizar a autodeterminação de que “num smartphone já comprado, também é possível criar por conta própria as funções realmente necessárias”

Análise das soluções de reprodução musical da Apple e de terceiros

App nativo da Apple

  • É possível reproduzir arquivos de música em pastas do iCloud usando o app Files, mas faltam funções básicas como gerenciamento de playlists, ordenação por metadados e manipulação da fila
  • A experiência oferecida não é otimizada para ouvir música

Apps de terceiros

  • Há vários apps externos na App Store, mas muitos seguem um modelo de cobrança por assinatura, e o nível de recursos varia bastante entre eles
  • Existem também apps pagos com compra única, como o Doppler, mas a experiência de busca e importação em pastas grandes do iCloud ainda não é fluida

A jornada técnica rumo ao “modo construtor”

  • O autor decidiu que precisava criar ele mesmo um app de player de música
  • Recursos desejados: busca full-text rápida em toda a pasta do iCloud, recursos de gerenciamento musical no nível de um app oficial de música (fila, playlists, ordenação etc.) e uma interface intuitiva

Primeira tentativa com React Native

  • Por incômodos anteriores com a experiência em Swift, o autor preferia React Native/Expo
  • O UI foi implementado sem grandes problemas com ajuda de templates open source, mas surgiram crashes e limitações funcionais no tratamento de acesso e sincronização do sistema de arquivos (pasta do iCloud)
  • Ao perceber que, pelas políticas de sandbox do iOS, não é possível acessar pastas externas sem permissões explícitas, ele migrou para Swift

Por que escolher SwiftUI

  • Aproveitamento do paradigma declarativo de UI do SwiftUI, além de suporte moderno a async/await e Swift Actor
  • Com separação rigorosa entre UI e lógica de dados, foi possível implementar um fluxo de dados limpo e concorrência no domínio
  • Também ajudou a otimizar o uso de LLMs (OpenAI o1, DeepSeek etc.), reduzindo dependências no código de UI gerado

Arquitetura do app e modelo de dados

  • O SQLite foi usado como armazenamento de dados e adotado no lugar de CoreData por permitir uso imediato de busca full-text (FTS5)

  • Os 3 principais modos/telas do app:

    1. Importação da biblioteca: salva em massa no banco os caminhos de arquivos de áudio por pasta do iCloud, permitindo busca e gerenciamento flexíveis
    2. Gerenciamento da biblioteca: playlists, categorização de faixas, edição etc.
    3. Reprodução musical: gerenciamento da fila (repetição, shuffle etc.) e controles básicos das músicas
  • Fluxo do usuário na importação da biblioteca:

    • No estado inicial vazio, o usuário seleciona uma pasta por meio de "Add iCloud Source" e faz a varredura da árvore
    • Quando a indexação termina, ele vai para a aba da biblioteca, com listas por palavra-chave e mini player
    • Ao adicionar novas músicas, elas são mescladas automaticamente em segundo plano

Camada lógica em estilo backend

  • Com base na experiência em startups de web/cloud, a camada lógica e a UI/ViewModel foram separadas de forma rigorosa
  • A camada de domínio (Swift actors) concentra a lógica principal de negócio (importação, busca, fila etc.), garantindo thread safety
  • As atualizações de UI são divididas de forma limpa via ViewModel, minimizando dependências entre sincronização de arquivos, reprodução e interface, o que melhora a manutenção

Implementando busca full-text com SQLite

  • A partir do iOS 11, é possível usar SQLite com suporte a FTS5 sem configuração adicional
  • Isso permite busca rápida sem depender de índice externo ou servidor
  • A biblioteca SQLite.swift é usada para consultas gerais, enquanto consultas FTS usam SQL escrito diretamente

Estrutura das tabelas FTS

  • songs_fts: indexa artist, title, album, albumArtist etc. das músicas
  • source_paths_fts: indexa caminhos de arquivos e nomes de arquivos
  • Elas existem em paralelo às tabelas principais e, na UI, são usadas apenas para busca (READ)
  • A atualização do índice é tratada com transações no banco, para manter a consistência dos dados

Busca fuzzy e ranking

  • Um wildcard é adicionado automaticamente ao final da entrada, com ordenação por relevância baseada em BM25
  • No geral, isso viabiliza uma estrutura de dados previsível, sem dependência de rede, e um poderoso ambiente de busca local

Sistema de arquivos do iOS e uso de bookmarks

  • Diferente do macOS, o iOS não oferece suporte a security-scoped bookmarks, o que reduz a persistência no acesso estendido a arquivos externos
  • Como apenas a informação do caminho é salva, ao tentar acessar novamente é preciso que o usuário autorize outra vez
  • Solução adotada: no momento em que o acesso é permitido, copiar o próprio arquivo para o sandbox do app
  • A cópia automática em segundo plano melhora a velocidade de indexação dos arquivos
  • Mesmo após reiniciar o dispositivo, ainda é difícil reproduzir diretamente arquivos externos, o que mostra como as restrições de acesso a arquivos no iOS são severas

Reprodução com AVFoundation e design da interface

  • O framework AVFoundation e o AVURLAsset são usados para analisar metadados de arquivos de áudio
  • Alguns campos, como número da faixa, são interpretados manualmente com base em tags ID3
  • Para reprodução de áudio, é usado AVAudioPlayer, e para integração com a Central de Controle são implementados MPRemoteCommandCenter e protocolos Delegate

Impressões após o desenvolvimento e reflexões sobre as políticas da Apple

Pontos incômodos

  • Ambiente restritivo do Xcode: o preview em tempo real do SwiftUI evoluiu, mas ainda não alcança a praticidade de VSCode ou Flutter
  • Falta de flexibilidade no editor: para usar Swift LSP no Neovim ou VSCode, são necessárias configurações adicionais e a experiência ainda é incompleta
  • Algumas partes do SDK ainda são centradas em Objective-C: em áreas como busca de metadados, faltam APIs mais amigáveis ao Swift moderno
  • Depuração do iCloud trabalhosa: não é possível implementar completamente recursos de nuvem no preview do SwiftUI, exigindo mocks montados manualmente

Pontos positivos

  • Com async/await, escrever código concorrente com I/O-bound ficou consideravelmente mais fácil
  • Bibliotecas nativas ricas: foi possível desenvolver recursos mais variados sem ficar preso às limitações de bindings open source
  • Design declarativo de UI do SwiftUI: ficou clara a produtividade elevada junto das vantagens do estilo React

Conclusão: desenvolver não deveria ser mais fácil?

  • Em 1,5 semana de desenvolvimento, o objetivo de criar um player de música local/offline foi alcançado
  • Na prática, porém, há restrições até para distribuir o próprio app: sem certificado de desenvolvedor, ele deixa de funcionar após 7 dias, e é necessário pagar US$ 99 por ano para o registro de desenvolvedor
  • Mesmo após o DMA Act da UE, o sideloading ainda não está totalmente liberado, e as restrições continuam para desenvolvedores individuais e amadores
  • PWAs também seguem limitados no iOS, com falta de suporte a APIs importantes (Web Bluetooth/USB/NFC, Background Sync etc.)
  • A IA reduziu a barreira de desenvolvimento, mas o iOS continua elevando essa barreira por regras artificiais
  • As limitações impostas a desenvolvedores independentes e aos direitos do usuário continuam, e o fechamento do iOS segue sendo um obstáculo à inovação

1 comentários

 
GN⁺ 2025-05-24
Comentários do Hacker News
  • Tenho experiência de 25 anos construindo minha coleção de músicas no formato FLAC e, no ano passado, comprei um celular Android e um cartão MicroSD de 1 TB, o que me deu uma enorme satisfação por poder carregar toda a minha música no bolso. Imagino que eu certamente não seja a única pessoa que não quer alugar música, perder o controle sobre ela, fazer streaming do que a indústria empurra ou lidar com anúncios. Acho muito legal ver casos de gente desenvolvendo o próprio aplicativo.
    • A tecnologia já acompanha isso há vários anos, mas a opinião é que eu só estou insistindo em um formato que não é adequado. Com uma boa recodificação, dá para colocar toda a música em um espaço muito menor com uma qualidade tão transparente que não dá para perceber diferença sonora. Recomenda-se manter os arquivos FLAC no desktop como backup.
    • Elogio dizendo que eu realmente sou alguém muito bom em colecionar. Na minha coleção, cerca de 25% está em formatos sem perda como FLAC/APE/ALAC/WavePack, e o tamanho já passa de 3 TB. Por isso, tenho dificuldade para ouvir música em movimento — compartilho que é difícil escolher com antecedência quais músicas transferir para o dispositivo móvel.
    • Continuo enfrentando no Android o problema de capas de álbum ou informações de título não serem refletidas corretamente, ou mudarem aleatoriamente. Isso parece um bug do Android, e pergunto se alguém já resolveu.
    • Eu também monto minha coleção pessoal só com FLAC, embora ainda não faça 25 anos. Já passei de 1 TB e estou muito satisfeito usando o servidor Navidrome e o cliente Symfonium. Como cartões microSD de 2 TB começaram a aparecer agora, provavelmente vou comprar um quando o preço cair mais.
  • Ouço música desde os tempos do winamp e, mesmo agora na era do streaming, ainda uso uma biblioteca local organizada por pastas. Como outros comentaristas, também fiz por hobby meu próprio player de música old school para ouvir música offline. É um app html/js de uma página, com controle total por teclado e uma função simples de fila (playlist). Recomendo dar uma olhada em https://nobsutils.com/mp.
    • Eu também sou da opinião, há 27 anos, de que a UI do winamp era realmente excelente. O ponto forte principal é a simplicidade de ter coleções de arquivos por pasta, reprodução aleatória geral e tocar apenas diretórios específicos.
    • Feedback dizendo que o app feito por você funciona muito bem.
    • Para mim, o foobar2000 era o player de música favorito; atualmente foi substituído pelo app Cog.
  • Eu mesmo desenvolvi um webapp com a função de ouvir álbuns inteiros e continuar do ponto em que parei ao trocar de dispositivo. Gosto de ouvir álbuns do começo ao fim, mas em serviços como YouTube Music já passei pela experiência de eles não lembrarem bem a posição de reprodução ou tornarem a troca de dispositivos incômoda. No webapp que fiz, basta colar uma URL e ele faz o download no servidor com yt-dlp, de onde dá para fazer streaming. Ele sempre lembra a posição de reprodução, então posso continuar no notebook do trabalho exatamente de onde parei no carro. Também funciona muito bem para adicionar mixes de outras fontes, como a NTS Radio.
    • Concordo que no YouTube Music não dá para salvar bem a fila nem trocar de dispositivo de forma fluida. Eu gostaria de experimentar esse webapp que o desenvolvedor criou.
  • Eu gostaria que o artigo tratasse não só do dispositivo físico, mas também do software que gerencia e reproduz isso. Alguns anos atrás, quis comprar um tocador de mp3 para meu filho de 10 anos e fiquei chocado com a falta de produtos adequados. A Apple descontinuou o iPod e deixou um enorme vazio no mercado, mas ninguém ainda conseguiu preenchê-lo direito. O iPod shuffle (no formato de pendrive USB) foi o melhor tocador de mp3 que já usei: pequeno, plugável e com bateria duradoura, o que me deixava muito satisfeito. O conceito de funcionar só no modo shuffle, sem tela, era até uma vantagem. Esse tipo de dispositivo simples também não está sendo reproduzido no mercado de hardware atualmente. Algumas pessoas podem ver isso como um problema de software/DRM, mas acho uma pena e gostaria que existisse um aparelho barato e portátil que só tocasse música.
    • Acho que a principal mudança não foi o desaparecimento do iPod, e sim a popularização do Spotify e dos smartphones. Na minha opinião, esses dois ocuparam quase todo o mercado e empurraram para fora todas as outras opções.
    • Compartilho a informação de que a Fiio está lançando vários produtos nessa categoria. exemplo 1 exemplo 2
    • Acho que não é um problema de hardware nem de software, mas de demanda. Fabricantes chineses vendem mini dispositivos de US$50~US$100, como um Mini iPhone 16 ou Mini S24, que têm funções de smartphone e também reproduzem música. A maioria dos pais provavelmente compraria esse tipo de aparelho para os filhos em vez de um tocador de mp3, e não são tantos os pais que querem adiar a entrega de um celular até os 14 anos, então a demanda do mercado acaba se formando assim.
    • A Sony ainda continua lançando bons players com a marca "walkman". link oficial Para uma criança de 10 anos pode ser um pouco caro, então recomendo procurar usado no eBay.
    • Uma lembrança nostálgica foi despertada ao pensar que provavelmente há algum tocador como o SanDisk Clip em algum lugar da casa.
  • Li esse texto com prazer e ainda nem terminei tudo. Gostei de ler sobre o processo do desenvolvedor ao tomar pequenas decisões detalhadas e os motivos por trás delas. Em quase todos os apps de música, o UX e o layout parecem parecidos, então sempre sinto que estou “lutando boxe” com todos esses apps. Apoio quem tenta algo novo.
  • Eu ainda uso apenas arquivos locais no app Apple Music. Deixo o serviço de streaming do Apple Music desligado, carrego todas as músicas no app Apple Music do macOS e depois conecto o celular ao notebook para sincronizar como se fosse 2007. Como minha música não muda com frequência, isso não é um problema para mim, e ainda sinto uma certa nostalgia com a sincronização por cabo.
    • Menciona-se que a sincronização automática por wi-fi com o iTunes ainda funciona bem.
  • Sobre a dúvida “por que uma empresa de TI inovadora coloca obstáculos ao desenvolvimento democrático de aplicativos”, citando uma frase do ex-CEO da Disney Michael Eisner, argumenta-se que a essência de uma empresa é buscar lucro, e que a Apple não é uma empresa inovadora ou democrática, mas orientada a receita. A menos que isso garanta mais lucro, reduzir barreiras de entrada para desenvolvedores ou abrir de forma democrática significaria abrir mão da receita da “galinha dos ovos de ouro” que é a loja oficial. Em outras palavras, a lógica de priorizar o lucro acima de tudo.
  • Para usuários de Android que mantêm uma biblioteca de música offline, recomendo fortemente o Musicolet. Funciona perfeitamente.
    • Também se enfatiza que o Symfonium é excelente por oferecer amplo suporte a Plex, Jellyfin, WebDAV, SMB etc.
  • Gostei muito de ler a análise técnica detalhada e, ao migrar de React Native para SwiftUI, percebi o quanto o código nativo torna o acesso ao iCloud e as otimizações mais fáceis. O truque de busca com SQLite FTS5 também foi marcante, e pretendo aproveitar isso no meu app de biblioteca.
  • Evitei Swift no começo por achar difícil, mas não concordo com a afirmação de que, depois da adição de async/await, ficou mais fácil escrever código concorrente. async traz conveniência na escrita, mas quando a escala cresce, a experiência é de que fica muito mais difícil entender o fluxo do código e a concorrência. Quando há problemas ainda não resolvidos, penso em alternativas como green lightweight threads. Existe a preocupação de que, no longo prazo, uma base em async possa até aumentar o custo de manutenção.
    • Vejo que o problema maior não é o conceito de concorrência em si, mas as limitações da abstração async/await. Uma boa concorrência deveria tornar o código mais fácil de entender e gerenciar conforme ele cresce, e a encapsulação centrada em processos/serviços parece ter grandes vantagens.
    • Para o objetivo de um player de música simples, imagino que o aumento de complexidade causado por async quase não será um problema.