# AutoDJ > Tocador de música que mixa como DJ e anda sozinho, no navegador. Toca arquivos > locais, Spotify e YouTube na mesma fila, com crossfade real, BPM medido e versão > SEM-VOZ separada por IA. Servidor em Go (arquitetura hexagonal) que só orquestra > a agenda — **o áudio toca no navegador**, não no servidor. Licença MIT. Este arquivo é o mapa do projeto para agentes e LLMs. Vai direto ao ponto: como rodar, onde ficam as coisas, e o que quebra se você não souber de antemão. - Código: https://github.com/andrebassi/autodj - Site do projeto: https://autodj-site.andrebassi.com.br - Instância pública: https://autodj.andrebassi.com.br - Idioma: documentação e interface em **pt-BR**; identificadores de código em **inglês** ## Rodar local em 3 comandos ```bash git clone https://github.com/andrebassi/autodj.git && cd autodj nix develop # go 1.26, node 22, pnpm, ffmpeg, aubio — tudo de uma vez task serve # servidor + interface em http://localhost:8099 ``` Sem Nix, o servidor sobe sozinho com repositório em memória: ```bash GOWORK=off PORT=8095 go run ./cmd/server ``` Depois, para encher a biblioteca: `task lib:scan FOLDER=/caminho/para/mp3s`. ### O que precisa existir na máquina | Ferramenta | Para quê | Sem ela | |---|---|---| | `ffmpeg` / `ffprobe` | metadados, capa embutida, análise (trim, LUFS, vocal) | upload falha e faixa não ganha marcadores | | `aubio-tools` | BPM | acervo inteiro fica sem BPM, **em silêncio** | | `nix` (opcional) | traz tudo acima de uma vez | instale ffmpeg e aubio à mão | ## ⚠️ Armadilhas que custam tempo (leia antes de depurar) - **Abra `http://localhost:`, NUNCA `http://127.0.0.1:`.** O YouTube se recusa a incorporar clipe monetizado quando a origem é um IP literal — o vídeo entra no deck e some. O redirect de OAuth também difere entre os dois hostnames. - **`GOWORK=off` é obrigatório.** O módulo é `autodj` (local, não `github.com/...`) e builda standalone; o Taskfile já exporta isso. - **Feature nova não aparece?** Provavelmente o binário Go é antigo servindo bundle novo. `task serve` reconstrói os dois. - **Sem `AUTODJ_*` de integração, as rotas correspondentes não existem (404) e a UI esconde a função.** Isso é degradação graciosa deliberada, não bug. - **Cobertura e changelog são portões de build**: `task cover` exige domínio 100% e adapters/app ≥90%; `task web:build` aborta se a git tag mais recente não tiver entrada em `web/app/lib/changelog.ts`. ## Onde fica o modelo de separação (Demucs v4 / htdemucs) - **Local**: binário `~/.autodj/bin/demucs` (`AUTODJ_DEMUCS_BIN`), pesos `~/.autodj/models/htdemucs.bin` (`AUTODJ_DEMUCS_MODEL`, ~80 MB, do Hugging Face `Retrobear/demucs.cpp`). Instalados por `scripts/build-demucs.sh`, que clona o `demucs.cpp` (MIT) em `~/.autodj/src`. - **Nuvem**: `pip install demucs` dentro do pod (imagem `pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime`); o modelo é baixado pela própria biblioteca no primeiro uso e **morre com o pod** — nunca toca o disco do operador. - ⚠️ É **inferência**, não treinamento: o modelo já vem treinado. ## Onde ficam as coisas ``` domain/ modelo puro, ZERO dependências externas — os invariantes moram aqui ports/ interfaces (inbound = casos de uso, outbound = mundo externo) app/ serviços que orquestram adapters/driven/ implementações: sqlite, postgres, ffprobe, audioanalyze, spotify, youtube, stemsep (local + nuvem), filestore adapters/driving/httpapi (REST) e ws (WebSocket) cmd/server wiring; cmd/serverkit resolve a estação por fingerprint web/app Next.js — components/, hooks/, lib/ docs/ prd.md, architecture.md, stories/, known-issues.md, pendencias.md ``` Direção de dependência: `adapters → ports → domain`. O domínio não importa banco, HTTP nem SDK de terceiro. ## Invariantes que NÃO se relaxam - **`spotify | youtube ⇒ mixable = false`.** Áudio com DRM e embed não têm PCM deste lado, então nunca entram no barramento de mixagem — sem crossfade real, beatmatch ou waveform. Imposto em duas camadas: domínio (`Track.Validate`) e banco (CHECK). Enfileirar e tocar essas fontes é normal; **mixar** é que não. - **Nunca reparentar o iframe do YouTube.** Mover um `