Handoff técnico · IMVU

Rádio na sala: um bot de música pro IMVU, do zero ao ar

O caminho completo que a gente percorreu — a arquitetura, cada fase da montagem e, principalmente, o porquê de cada peça. Feito pra você refazer os passos e ter o seu próprio DJ na sua sala.

★ leia antes de montar

Existem dois caminhos aqui — e vale escolher antes de pôr a mão na massa. O capítulo 03 (As fases da montagem) monta a versão com navegador: um Chromium invisível que lê a página da sala. É a forma mais didática de entender cada peça, e foi como a gente começou.

Mas hoje a gente não usa mais navegador. A versão que roda de verdade é um cliente WebSocket ~10x mais leve, e ela reaproveita quase tudo daqui — só a forma de conversar com o chat muda. Se você seguir as fases em ordem, vai montar o Chromium primeiro e só depois descobrir que ele virou dispensável.

Já quer ir direto ao método atual? Pule pra A virada — o caminho dourado: ela te leva do zero ao ar sozinha, reusando as fases que não mudaram.

// 01

A ideia em uma frase

Antes dos passos, entenda o desenho. Sabendo o que cada peça resolve, você adapta em vez de copiar cego.

Uma conta IMVU separada vira o "bot". Ela roda 24/7 numa máquina virtual grátis que faz duas coisas ao mesmo tempo: transmite um rádio de música (um stream de áudio) e mantém um navegador invisível logado na sua sala, lendo o chat e obedecendo comandos. O IMVU aponta pro endereço do rádio; as pessoas na sala ouvem a música e conversam com o bot.

Por que separado assim

Cada peça resolve um problema real que a gente só descobriu apanhando. As seções abaixo explicam cada escolha — leia os "porquês", eles valem mais que o código. Nota: a gente começou com um navegador invisível (Chromium); depois evoluiu pra um cliente sem navegador, bem mais leve — o capítulo A virada conta como e por quê (e por que o "bot = Chromium" no diagrama é a versão original).

// 02

Antes de começar

O que ter em mãos. Nada aqui custa dinheiro.

Instalar as ferramentas do PC de uma vez. Escolha seu sistema, clique em copiar e cole no seu terminal (a página não roda nada por você — você vê o comando antes de rodar).

# Windows 10/11 - o winget ja vem incluso (Terminal ou PowerShell)
winget install OpenJS.NodeJS.LTS
winget install yt-dlp.yt-dlp
winget install Gyan.FFmpeg
winget install Git.Git
# macOS - via Homebrew (instale o brew antes, em brew.sh)
brew install node yt-dlp ffmpeg git
# Debian/Ubuntu - o Node do apt pode ser antigo; p/ v18+ veja nodejs.org
sudo apt update
sudo apt install -y nodejs npm ffmpeg git python3-pip
python3 -m pip install -U yt-dlp
Cuidado

Guarde segredos (sessão de login do bot, chave do Gemini, token do DuckDNS) fora do controle de versão. Um .gitignore com auth.json, *.key, *.token e cache/ evita vazar tudo no primeiro git push.

// 03

As fases da montagem

A ordem importa — cada fase se apoia na anterior. Monte e teste no seu PC primeiro; só depois suba pra nuvem.

0Protótipo
No seu PC · Node + Playwright

Entrar na sala e ler o chat

O bot é, no fundo, um navegador automatizado. Use o Playwright pra abrir um Chromium, logar na conta do bot uma vez e salvar a sessão (um login.js que grava um auth.json). Depois é só reabrir a sala reaproveitando essa sessão.

Dentro da sala, o IMVU conversa por um WebSocket (o "IMQ"). O bot escuta as mensagens que chegam por ele e é assim que ele "lê" o chat e detecta comandos. Comece simples: logar, entrar na sala, imprimir no terminal cada mensagem que aparece.

Por quê Playwright

O IMVU não tem API pública de chat. A forma confiável de participar da sala é ser um cliente de verdade — um navegador logado. Headless (invisível) pra rodar num servidor sem tela.

1Rádio
No seu PC · server.js

O stream de áudio (a jukebox)

Um servidor HTTP simples que transmite um MP3 contínuo numa porta (ex.: :8000). Ele tem uma pasta de músicas "filler" (as que tocam sozinhas), embaralha a ordem, e expõe rotas internas pra enfileirar e pular faixas (/add, /skip, /status). O bot fala com essas rotas por localhost.

Por quê um processo separado do bot

Mais tarde você vai querer reiniciar o bot (ele acumula memória) sem cortar a música. Manter o rádio como um serviço próprio faz o som continuar mesmo quando o bot reinicia.

2Comandos
Ligando as duas metades

Comandos de chat viram músicas

Agora conecte o que o bot lê do chat à jukebox. Uma mensagem tipo !play nome da música faz o bot chamar o stream por localhost e enfileirar. !skip, !queue etc. seguem a mesma ideia.

3Ponte
No seu PC · resolver + túnel

Resolver músicas do YouTube (o bridge)

Pra tocar "qualquer música", o bot precisa baixar do YouTube — e aí mora a maior armadilha: o YouTube bloqueia IPs de datacenter, então a VM não consegue baixar sozinha. A solução é um pequeno agente HTTP no seu PC de casa (IP residential, que o YouTube aceita) rodando o yt-dlp. A VM alcança esse agente por um túnel SSH reverso.

Cuidado

Isso significa que !play/!add só funcionam com o seu PC ligado e o bridge rodando. Todo o resto (rádio, chat, IA) funciona sem ele. Se não quiser essa dependência, dá pra tocar só a pasta local de músicas e dispensar o YouTube.

4Nuvem
Oracle Always Free · systemd

Subir tudo pra máquina virtual

Crie uma instância Always Free (a E2.1.Micro, 1 GB de RAM, é a mais fácil de conseguir; a A1 ARM dá mais folga se aparecer vaga). Ubuntu. Instale Node, o Chromium do Playwright e o ffmpeg, mande os arquivos por scp, e registre os dois serviços no systemd pra subirem no boot e reiniciarem sozinhos.

# esqueleto de um serviço systemd (/etc/systemd/system/bot.service)
[Service]
ExecStart=/usr/bin/node /home/ubuntu/bot/bot.js
Restart=always
WorkingDirectory=/home/ubuntu/bot
Cuidado · 1 GB é apertado

O Chromium sozinho come ~500 MB. Ative swap (ex.: 2 GB em /swapfile) ou a VM trava. E esqueça 3D/WebGL nessa máquina — a gente tentou, deu out-of-memory. Rode o navegador sem 3D.

5HTTPS
DuckDNS + Caddy + firewall

Deixar o rádio público e seguro

O IMVU Next é uma página HTTPS e recusa endereços de stream em HTTP puro — TLS é obrigatório. Mas o Let's Encrypt não emite certificado pra um IP "pelado", e é por isso que o DuckDNS existe: ele te dá um domínio grátis apontando pro IP da VM. Na frente de tudo vai o Caddy, que pega o certificado HTTPS automaticamente e repassa pro stream.

# Caddyfile — repassa 443 pro stream local
seu-nome.duckdns.org {
    reverse_proxy localhost:8000 {
        flush_interval -1   # ESSENCIAL: sem isso o Caddy segura o buffer e o som trava
    }
}
Cuidado · duas camadas de firewall

Na Oracle, uma porta só abre se as duas deixarem: o firewall do sistema (iptables) e a "Security List" da OCI. Abra 22, 80 e 443; deixe a 8000 fechada pro público (só o Caddy fala com ela por dentro). E lembre: o IP da Oracle é efêmero — um cron atualizando o DuckDNS a cada 5 min mantém o domínio certo se o IP mudar.

6Conectar
Nas configurações da sala

Apontar o IMVU pro rádio

No painel de edição da sua sala no IMVU, cole a URL do stream (https://seu-nome.duckdns.org/stream) no campo de música. Pronto: quem entrar na sala já ouve o rádio. O bot, logado na conta dona da sala, aparece no chat.

7Robustez
O que mantém ele de pé sozinho

Sobreviver 24/7 sem babá

Um bot que cai de madrugada não serve. Estas defesas nasceram, uma a uma, de problemas reais:

  • Heartbeat anti-ocioso: o IMVU chuta avatares parados. O bot manda uma notinha (♫) de tempos em tempos se ficou quieto, pra parecer ativo.
  • Flags anti-throttle no Chromium: aba invisível tem os timers estrangulados pelo navegador, o que mata o keepalive do WebSocket e derruba o bot a cada ~8 min. Ligue --disable-background-timer-throttling (e as irmãs dela).
  • Self-heal: se o WebSocket cair, reconecta sozinho.
  • Watchdog: um timer independente da página que reinicia o processo se ele travar (na máquina de 1 GB, às vezes a página congela).
  • "Breather" (respiro): um restart programado (ex.: 2×/dia) pra limpar a memória antes que o vazamento lento estoure em OOM. Como o stream é separado, a música não para.
  • Detecção de kick: consultando a lista de participantes da sala, o bot percebe se foi removido e reentra.
Lição geral

Quase toda essa lista é fruto de "por que ela sumiu de novo?". Anote seus próprios sintomas — o que parece um bug é quase sempre o IMVU ou o Chromium reagindo a algo específico.

8Alma
Opcional · Gemini + memória

Personalidade e IA

Com a base de pé, o resto é sabor. Ligue um modelo (a gente usa o Gemini, tem tier grátis) pra dar respostas com uma persona; deixe o bot decidir sozinho quando a mensagem é pra ele (respondendo "pular" quando não for, pra não se intrometer). Dá pra adicionar saudações, memória de quem já visitou, conhecimento da própria sala/móveis e uma janela de conversa contínua.

Cuidado · o apelido "-latest"

Se usar um modelo com nome tipo -latest, saiba que ele "rola pra frente" sozinho e um dia pode quebrar em silêncio (já aconteceu aqui). Fixe uma versão específica e teste depois de qualquer troca.

// 04 · atualização

A virada: quando o navegador virou dispensável

★ método atual · sem navegador

As fases acima são como a gente começou — e ensinaram tudo. Este capítulo é o que a gente roda hoje, e ele se banca sozinho: lá embaixo tem um passo a passo do zero que reaproveita as fases que não mudaram e ensina, com calma, a única parte que de fato mudou.

O bot da Fase 0 era um Chromium invisível pilotado pelo Playwright. Funcionava, mas era um mensageiro caríssimo — o navegador inteiro só pra carregar uns recados. Aí a ficha caiu: a "presença" do IMVU na sala é só um protocolo — um WebSocket (o tal IMQ) mais algumas chamadas REST. Dá pra falar esse protocolo direto, sem navegador nenhum.

Foi o que fizemos: engenharia reversa do protocolo — observando os quadros que um navegador real troca com o IMVU, partindo de um build antigo achado no GitHub e lapidando pro nosso uso — e escrevemos um cliente sem navegador ("browserless") que loga, entra na sala, lê o chat, senta, fala e confere os participantes falando IMQ na lata. Mesma conta, mesma sala, mesmos comandos — zero Chromium.

Por que muda tudo — adeus, dor de RAM

O Chromium sozinho comia ~500 MB (e vazava até dar out-of-memory lá pelas ~19 h de uptime). O cliente em Node puro fica em ~50 MB. De quebra, somem TODAS as gambiarras que só existiam por causa do navegador: o swap obrigatório, o "esqueça 3D/WebGL", as flags anti-throttle "load-bearing", o watchdog de página travada e o "breather" que reiniciava só pra limpar memória. Sem navegador, nada disso precisa existir.

A parte que importa pra VOCÊ: o tamanho da máquina deixou de mandar

Com o bot tão leve, aquela agonia de "1 GB é pouco" evapora — e vale dizer alto: talvez você nem precise de uma VM. Um PC de casa decente (um Windows 11 com 16 GB de RAM, digamos) roda o bot, o stream e o resto tudo localmente, de sobra. A nuvem grátis servia mesmo era pra ter uma máquina sempre ligada e um endereço público; se a sua casa já resolve isso, todo o esqueleto de cima — Oracle, swap, systemd — vira opcional. Use a nuvem se ela te resolver um problema, não por obrigação. As fases acima são o caminho mais barato, não o único.

E o melhor: o cliente sem navegador reaproveitou quase tudo. O rádio/jukebox (server.js), a ponte do YouTube, a camada de IA e as defesas de sala nunca dependeram do Chromium — só a metade "navegador" do bot virou "protocolo direto". As outras fases seguem valendo palavra por palavra. E foi essa leveza que abriu espaço pra crescer depois (tocar em várias salas ao mesmo tempo, por exemplo, sem a máquina suar).

O caminho atual, do zero

Você não precisa montar o Chromium pra chegar aqui. Se está começando agora e quer só o que roda hoje, siga esta trilha: os passos que não mudaram apontam de volta pras fases lá em cima (é literalmente o mesmo), e o passo do meio — o coração novo — vem explicado com calma.

  1. Escolha a casa da máquina. Uma VM sempre ligada (Oracle Always Free) ou um PC de casa que fique ligado — agora tanto faz, o bot é leve. Só precisa de Node.js 18+.
    Igual à Fase 4 se você for de nuvem — e, como o bot emagreceu, aqui você já pode pular o swap.
  2. Suba o rádio e a ponte do YouTube. A jukebox (server.js) que serve o MP3, mais o resolver no seu PC que baixa as músicas.
    Igual às Fases 1 e 3 — palavra por palavra. O stream nunca dependeu do navegador, então nada muda aqui.
  3. Deixe público e seguro. Domínio grátis no DuckDNS e o Caddy pegando o HTTPS na frente do stream.
    Igual à Fase 5. (Num PC de casa, é só isto que você precisa resolver: um jeito de ter endereço fixo e TLS — um túnel ou um domínio dinâmico já servem.)
  4. O coração novo: o cliente IMQ, sem navegador. Aqui está a única peça que muda de verdade. No lugar do Chromium lendo a página, um cliente em Node fala o protocolo do IMVU direto. São quatro movimentos:
    • Logar (REST). Você manda as credenciais da conta-bot pro endpoint de login do IMVU e guarda a sessão que volta (os cookies/o "sauce"). É exatamente o login que o site faz por baixo — só que na mão. A senha fica no ambiente da máquina, nunca no código.
    • Abrir o IMQ (WebSocket). Com a sessão na mão, você abre um WebSocket pro message queue do IMVU e assina a fila da sua sala. É esse cano que entrega os eventos: mensagens do chat, quem entrou/saiu, os assentos.
    • Ouvir e reagir. Cada evento que chega é um JSON simples. Você olha o tipo ("mensagem de chat", "participante entrou"...) e dispara a mesma lógica de comando que o bot já tinha — !play, !skip e cia. não mudam em nada.
    • Falar e sentar. Pra responder no chat ou sentar num lugar, você manda um evento de volta pela mesma fila — o inverso do que ouve.
    Na prática isso vira um arquivo só — imq-client.js — que embrulha essa camada; o resto do bot.js nem percebe que o navegador sumiu.
    Onde achar os quadros

    O IMQ não é documentado. Você descobre o formato dos eventos observando um login real (as ferramentas de rede do navegador, aba WebSocket) ou partindo de um build de referência — foi o que a gente fez, achando um antigo no GitHub e lapidando. Reserve um tempo pra essa parte; é o único trecho "de detetive" do projeto.

  5. Registre no systemd — agora bem mais magro. Mesmo esquema da Fase 4 (dois serviços que sobem no boot e reiniciam sozinhos), mas você apaga tudo que era muleta do navegador nas Fases 4 e 7: sem swap obrigatório, sem "esqueça 3D/WebGL", sem flags anti-throttle, sem watchdog de página travada, sem o reinício "breather" pra limpar memória. Some tudo — não precisa mais existir.
    As outras defesas da Fase 7 — heartbeat, self-heal, detecção de kick — continuam valendo.
  6. Aponte a sala pro rádio. Cole a URL do stream no campo de música da sala e pronto: o bot está no ar.
    Igual à Fase 6. E se quiser dar alma ao bot, a Fase 8 (IA) também entra sem mudar nada.
Cuidado · o preço da engenharia reversa

Falar o protocolo direto é leve e rápido, mas é um protocolo não-oficial: se o IMVU mudar os quadros do IMQ, seu cliente quebra e você conserta na mão (um navegador de verdade se adaptaria sozinho). É uma troca consciente — muito mais leve, um tico mais frágil. Aqui valeu demais a pena.

// 05

Armadilhas, num só lugar

Se ler só uma seção, leia esta. Cada linha custou horas de debug.

// 06

Mapa dos arquivos

A grosso modo, quem faz o quê. Os nomes são os que usamos — o seu pode variar.

bot.jsO bot: entra na sala, lê o chat pelo WebSocket, dispara comandos, saudações, IA e as defesas (heartbeat, self-heal, watchdog).
server.jsO stream/jukebox: transmite o MP3, gerencia a fila e a pasta de músicas, expõe as rotas internas.
ai.jsA camada de IA: monta o prompt (persona + contexto da conversa) e chama o modelo.
resolver.js / bridge.jsA ponte do YouTube: o yt-dlp resolve/baixa no PC; a VM alcança por túnel.
config.jsAjustes num lugar só: URL da sala, palavra que "chama" a IA, tempos, portas.
login.jsRoda uma vez pra gerar a sessão salva (auth.json) da conta do bot.
messages/ · scene/Textos editáveis (saudações, frases) e o "conhecimento" da sala (tema, móveis) que a IA usa.
Playlist de filler da Sofia carregando…