Todos os artigos
OpenAIRealtime APIWebSocketAI

Testar a OpenAI Realtime API localmente por um túnel

A OpenAI Realtime API conecta clientes por WebSocket ou WebRTC. Para conexões do lado do servidor, você pode acessar a OpenAI diretamente de qualquer máquina com internet. Para conexões do lado do cliente — que é a maior parte do que você realmente vai querer construir com isso — o navegador precisa de uma origem segura e seu backend precisa emitir tokens efêmeros. Ambos funcionam por um túnel. Há alguns detalhes a saber.

Duas formas de conectar, dois motivos para tunelar

A Realtime API suporta conexões do lado do servidor (seu backend abre um WebSocket para a OpenAI) e conexões do lado do cliente (um navegador abre uma conexão peer WebRTC ou um WebSocket usando um token efêmero que seu backend emite). O caminho do servidor não precisa de túnel. O do cliente quase sempre precisa.

Por que o lado do cliente precisa de HTTPS:

  • As permissões de microfone do navegador exigem uma origem segura.
  • O getUserMedia do WebRTC e o tratamento de ICE funcionam melhor em HTTPS.
  • Service workers (se você tiver algum) precisam disso.
  • Se você chama o endpoint /session do seu backend para obter um token efêmero, esse backend também tem que ser HTTPS se o seu frontend for.

O primeiro ponto você pode contornar com flags do navegador. Não faça. Use um túnel e viva no mundo real.

O formato de um app Realtime em desenvolvimento

Um app realtime mínimo tem três partes:

  1. Um frontend que captura a entrada do microfone e renderiza a saída de áudio.
  2. Uma rota de backend que emite um token efêmero acessando o endpoint /v1/realtime/sessions da OpenAI com sua API key real.
  3. Uma conexão WebRTC ou WebSocket direta do navegador para a OpenAI, usando o token efêmero.

Seu túnel expõe o frontend + backend (o mesmo domínio na maioria das configurações). O tráfego realtime de verdade vai do navegador para a OpenAI, não pelo seu túnel — essa conexão é direta por HTTPS/WSS.

Configuração rápida com PortPreview

  1. Inicie seu servidor de desenvolvimento (Next.js, Vite, o que for) na porta 3000 ou 5173.
  2. Execute npx portpreview 3000.
  3. Abra a URL HTTPS num navegador. Os avisos de permissão de microfone funcionam normalmente.
  4. Acesse seu endpoint emissor de token, obtenha um token efêmero, abra a conexão realtime.
  5. Fale, receba uma resposta em streaming.

Se você usa Vite, vai precisar da config de allowedHosts e HMR de Vite + túnel. Se está no Next.js com edge runtime em algum lugar, cuidado com a config de runtime em rotas que precisam de crypto do Node.

Upgrades de WebSocket por túneis

Conexões realtime são WebSocket (ou WebRTC, que em grande parte contorna o túnel). Qualquer túnel que você use precisa encaminhar corretamente a requisição HTTP Upgrade. A maioria encaminha — PortPreview, quick tunnels da Cloudflare, ngrok todos tratam upgrades de WebSocket. Se o seu não trata, a conexão falha em silêncio no navegador com uma mensagem genérica WebSocket closed before connected e sem detalhe útil.

Teste o upgrade com wscat se estiver em dúvida. Conecte-se a wss://your-tunnel.portpreview.dev/anything e observe o handshake.

Os truques de desenvolvimento que ajudam

Inspecione a requisição de emissão de token

Seu frontend chama uma rota de backend que chama a OpenAI. O bug de desenvolvimento mais comum aqui é uma requisição mal configurada para /v1/realtime/sessions — nome de modelo errado, voice errada, modalities erradas. Seu túnel captura a requisição do frontend para o backend, mas não o salto do backend para a OpenAI. Registre essa requisição no servidor, ou faça proxy por seu túnel rodando as duas camadas localmente.

Incompatibilidades de formato de áudio

A Realtime API usa PCM16 por padrão com uma sample rate configurável. Se você injeta áudio de outro formato, o modelo ou rejeita ou alucina. O MediaRecorder do navegador costuma te dar Opus ou WebM — você vai precisar tratar a conversão ou usar o caminho WebRTC que faz isso por você.

Expiração de token em sessões longas

Tokens efêmeros têm vida curta. Se você testa uma sessão mais longa que o TTL do token, renove conforme um cronograma. O SDK da Realtime tem helpers para isso; fazer na mão significa observar o evento session.expired e emitir um novo token antes de o antigo morrer.

Como isso fica em produção

A única mudança real de desenvolvimento para produção é a URL: substitua o hostname do túnel pelo seu domínio real. O endpoint emissor de token fica no seu backend. A conexão WebRTC/WebSocket do navegador para a OpenAI é o mesmo caminho de código. Já vimos times complicarem demais e tentarem fazer proxy do tráfego realtime pelo backend — não faça, isso adiciona latência e quebra o modelo que o SDK da OpenAI assume.

Para a oferta paralela da Anthropic (que se parece mais com um loop de tool use do que com um WebSocket em streaming), veja Anthropic tool use e webhooks localmente. Entre na lista de espera do PortPreview para um túnel que trata upgrades de WebSocket por padrão.

Perguntas frequentes

Posso testar a OpenAI Realtime API no localhost?
Conexões do lado do servidor não precisam de túnel. Conexões do lado do cliente a partir de um navegador precisam de HTTPS para permissões de microfone e endpoints de tokens efêmeros. Use um túnel para expor seu servidor de desenvolvimento por HTTPS e depois conecte o navegador diretamente à OpenAI com o token efêmero.
Meu túnel precisa suportar WebSockets para a Realtime API?
Se você usa o transporte WebSocket, sim — o túnel precisa encaminhar requisições de upgrade HTTP. A maioria dos túneis modernos faz isso, mas vale testar com wscat antes de caçar um bug de conexão fantasma. O WebRTC contorna o túnel para o próprio tráfego realtime.
Por que preciso de tokens efêmeros para conexões realtime no navegador?
Colocar sua API key completa no navegador é um desastre de segurança. Seu backend emite um token efêmero de vida curta restrito a uma sessão realtime. O navegador usa esse token para conectar diretamente à OpenAI sem nunca ver sua API key real.