1

[Pitch] Estou construindo um player de Spotify + Local no terminal em Rust porque o oficial come 600MB de RAM - isi-music

Começando pelo o começo, eu estava tendo muitos problemas com o Spotify enquanto jogava(na época meu pc era uma bomba) e comecei a desenvolver um player de música via terminal, no começo foi apenas para conseguir ouvir minhas músicas curtidas, depois vi o projeto tomando forma e comecei a tentar melhorar ele e atualmente creio que está muito bom para um player desenvolvido por uma pessoa, claro ninguém tá puro, usei IA em várias partes, muito para pesquisa e refatoração.

Bem, como vinha dizendo, comecei a desenvolver este projeto a partir de um problema, pouca ram + cpu integrada, na época era só 8gb de ram e o Ryzen 4600g pocando o CS2(Atualmente nem tempo eu tenho mais para jogar kkkk). Era papo o Spotify estar tocando uma música e consumindo 600mb de ram, para 8gb de ram é complicado...
Antes de começar a desenvolver este projeto, testei o Tauon(um player muito bom). Porém, tinha um problema nisso, só tinha suporte a músicas locais e eu queria usar o Spotify(ele até tinha, só que o Spotify tá ficando muito fechado e dificultando o uso da api) e também ele consumia uma quantidade de ram relativamente alta, não tanto quanto o Spotify. Usei ele por 2 meses e nessa época eu tinha migrado para o Linux, especificamente CachyOs + Hyprland(Modinha) e simplesmente era impraticável rodar CS2 em cima do XWayland, muitos travamentos, demora para dar o input, muitos problemas, porém eu aprendi muita coisa, foi nesse OS que comecei a desenvolver o isi_music, no começo ele só tinha algumas funções básicas, literalmente só liked songs e sim foi inspirado no Spotify-tui que atualmente está EOL, pra mim na época era ótimo.

Agora parando de papo furado, vamos aos detalhes técnicos.

Primeiro, a escolha de stack

  • Rust
    Crates do cargo:
  • Librespot(Literalmente a melhor crate para lidar com Spotify)
  • Tokio(Lidar com requests)
  • Ratatui(Não tenho nem o que falar, simplesmente lindo)

Fora essas principais, tem um monte de outras que fui adicionando conforme precisava: rusqlite pro cache, rodio e symphonia pra tocar arquivos locais, reqwest pras chamadas da Web API, crossterm pra lidar com input do terminal.

Agora sobre os problemas que eu esbarrei e acho que vale compartilhar.

O Spotify tem duas APIs e você precisa das duas, isso eu demorei pra entender no começo. No começo funcionava normal com apenas o client id do app em dev mode, aí do nada parou e tive que ir pro client id oficial do librespot. Resumindo, a Web API é REST, retorna JSON, serve pra buscar playlists, álbuns, liked tracks, search. O Spotify Connect é o protocolo binário que faz o streaming de áudio de verdade, e é o que o librespot implementa. São Client IDs diferentes, fluxos OAuth diferentes. O isi-music autentica nos dois durante o setup, os dois com PKCE (sem client_secret). Se você só quer streaming pode pular a Web API e deixar o Client ID em branco.

O librespot também precisou de um patch. Tem um cenário de rede onde o login5 falha e não tem fallback na versão original, aí você mantém um patch local em patches/librespot-core/ aplicado via path override no Cargo.toml. Funciona, mas o lado chato é que toda vez que sobe a versão do librespot tem que reaplicar o patch na mão e verificar se nada quebrou. -_-

Construir TUI é mais difícil do que parece. O terminal é literalmente caracteres, você não tem flexbox, não tem nada disso. O Ratatui ajuda demais mas o layout é por sua conta. O que funcionou pra mim foi uma árvore de layout que divide a tela recursivamente em retângulos com pesos, cada nó é uma divisão horizontal ou vertical. Com isso consigo 6 layouts diferentes sem reescrever código de renderização(Você consegue modificar no arquivo theme.toml). E como o Ratatui é immediate mode, você redesenha tudo a cada frame, o backend faz diff entre o frame atual e o anterior e manda só as mudanças pro terminal. Isso é eficiente mas se a árvore de layout for muito funda o diff fica bemm caro, mantive em 3 níveis no máximo e uso force_clear só quando realmente preciso (tipo quando toggle o compact mode).

O tema reativo, na época que eu usava o Tauon ele já tinha isso, aí recentemente lembrei dele por causa de um post no reddit. A ideia é simples: extrair as cores dominantes da capa do álbum e pintar a interface com elas. A extração roda numa thread separada pra não travar a UI, uso k-means simplificado nos pixels da imagem. O cross-fade em si roda no loop principal, guardo as cores de origem, destino, e um progresso de 0 a 1 que avança a cada tick baseado no delta time. O usuário controla a duração no theme.toml com reactive_cross_fade_ms.Tá bem redondinho, lembrando que ele vem false, para ativar é só apertar T e habilitar, no T tem o last.fm também. :)

Cache eu comecei com JSON files e troquei pra SQLite. Liked tracks precisa paginação com cursor (added_at + uri), que com SQL é bem de boa e com JSON é uma merda. WAL mode do SQLite permite leitura concorrente sem bloquear writes, importante porque a UI lê o cache enquanto o fetcher escreve. E com 2000+ liked tracks o JSON fica grande e lento de parsear, SQLite indexa e resolve. A conexão é compartilhada via Arc<Mutex> com spawn_blocking no runtime do Tokio.

Cross-compile ARM64 foi o inferno das dependências C. Três complicam: alsa-sys (linka libasound2, não é bundled), libopus_sys (compila libopus via cmake), libsqlite3-sys (compila SQLite via cc). Todas precisam de cross-compiler. Pra piorar, se você usar native-tls/openssl é mais uma. A solução foi usar rustls em toda a árvore de dependências e eliminar openssl-sys do build. Pra verificar: cargo tree -i openssl-sys tem que retornar "did not match any packages".

Também tem daemon mode com IPC. No Linux usa Unix socket, no Windows usa named pipe. Permite rodar em background e controlar via CLI: isi-music --daemon pra iniciar, --play pra tocar, --status pra ver o que tá tocando, --quit-daemon pra parar.

Integrações: MPRIS2 no Linux (funciona com playerctl e Waybar), Discord Rich Presence, e Last.fm scrobbling (começa depois de 50% da música ou 4 minutos, o que vier primeiro).

O projeto é open source (MIT), roda em Linux e Windows, tem instalador via curl/PowerShell e Homebrew tap. Enfim, post longo e é isso, caso alguém fique interessado no projeto, o link está abaixo e se quiser ajudar com uma estrelinha, eu ficarei com os olhinhos brilhando hauigfawuf

Ah, e tenho 19 anos, esse é meu primeiro projeto que cresce de verdade e tô apanhando que nem mulher de bandido pra manter ele de pé kkkkkk

Repo: https://github.com/glrmrissi/isi_music

Se alguém tiver perguntas sobre algum desses pontos ou quiser contribuir, é só mandar o papo

Carregando publicação patrocinada...