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
getUserMediado WebRTC e o tratamento de ICE funcionam melhor em HTTPS. - Service workers (se você tiver algum) precisam disso.
- Se você chama o endpoint
/sessiondo 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:
- Um frontend que captura a entrada do microfone e renderiza a saída de áudio.
- Uma rota de backend que emite um token efêmero acessando o endpoint
/v1/realtime/sessionsda OpenAI com sua API key real. - 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
- Inicie seu servidor de desenvolvimento (Next.js, Vite, o que for) na porta 3000 ou 5173.
- Execute
npx portpreview 3000. - Abra a URL HTTPS num navegador. Os avisos de permissão de microfone funcionam normalmente.
- Acesse seu endpoint emissor de token, obtenha um token efêmero, abra a conexão realtime.
- 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.