Todos los artículos
OpenAIRealtime APIWebSocketAI

Probar la OpenAI Realtime API en local a través de un túnel

La OpenAI Realtime API conecta clientes por WebSocket o WebRTC. Para conexiones del lado del servidor, puedes llegar a OpenAI directamente desde cualquier máquina con internet. Para conexiones del lado del cliente —que es la mayor parte de lo que querrías construir con esto— el navegador necesita un origen seguro y tu backend debe emitir tokens efímeros. Ambas funcionan a través de un túnel. Hay algunos detalles que conviene saber.

Dos formas de conectar, dos razones para tunelizar

La Realtime API admite conexiones del lado del servidor (tu backend abre un WebSocket hacia OpenAI) y conexiones del lado del cliente (un navegador abre una conexión peer WebRTC o un WebSocket usando un token efímero que tu backend emite). El camino del servidor no necesita túnel. El del cliente casi siempre sí.

Por qué el lado del cliente necesita HTTPS:

  • Los permisos de micrófono del navegador requieren un origen seguro.
  • El getUserMedia de WebRTC y el manejo de ICE funcionan mejor con HTTPS.
  • Los service workers (si tienes alguno) lo necesitan.
  • Si llamas al endpoint /session de tu backend para obtener un token efímero, ese backend también tiene que ser HTTPS si tu frontend lo es.

Puedes saltarte el primero con flags del navegador. No lo hagas. Usa un túnel y vive en el mundo real.

La forma de una app Realtime en desarrollo

Una app realtime mínima tiene tres partes:

  1. Un frontend que captura la entrada de micrófono y reproduce la salida de audio.
  2. Una ruta de backend que emite un token efímero llamando al endpoint /v1/realtime/sessions de OpenAI con tu API key real.
  3. Una conexión WebRTC o WebSocket directa del navegador a OpenAI, usando el token efímero.

Tu túnel expone el frontend + backend (la misma dominio en la mayoría de configuraciones). El tráfico realtime real va del navegador a OpenAI, no a través de tu túnel: esa conexión es directa por HTTPS/WSS.

Configuración rápida con PortPreview

  1. Inicia tu servidor de desarrollo (Next.js, Vite, lo que sea) en el puerto 3000 o 5173.
  2. Ejecuta npx portpreview 3000.
  3. Abre la URL HTTPS en un navegador. Los avisos de permiso de micrófono funcionan con normalidad.
  4. Llama a tu endpoint emisor de tokens, obtén un token efímero, abre la conexión realtime.
  5. Habla, recibe una respuesta en streaming.

Si usas Vite, necesitarás la config de allowedHosts y HMR de Vite + túnel. Si estás en Next.js con edge runtime en algún sitio, cuidado con la config de runtime en rutas que necesitan crypto de Node.

Upgrades de WebSocket a través de túneles

Las conexiones realtime son WebSocket (o WebRTC, que en su mayoría evita el túnel). Cualquier túnel que uses debe reenviar correctamente la petición HTTP Upgrade. La mayoría lo hace: PortPreview, los quick tunnels de Cloudflare y ngrok manejan los upgrades de WebSocket. Si el tuyo no, la conexión falla en silencio en el navegador con un genérico WebSocket closed before connected y sin detalle útil.

Prueba el upgrade con wscat si no estás seguro. Conéctate a wss://your-tunnel.portpreview.dev/anything y observa el handshake.

Los trucos de desarrollo que ayudan

Inspeccionar la petición de emisión de token

Tu frontend llama a una ruta de backend que llama a OpenAI. El bug de desarrollo más común aquí es una petición mal configurada a /v1/realtime/sessions: nombre de modelo equivocado, voz equivocada, modalities equivocadas. Tu túnel captura la petición del frontend al backend, pero no el salto del backend a OpenAI. Registra esa petición en el servidor, o haz proxy a través de tu túnel ejecutando ambas capas en local.

Desajustes de formato de audio

La Realtime API usa PCM16 por defecto con una sample rate configurable. Si metes audio de otro formato, el modelo lo rechazará o alucinará. El MediaRecorder del navegador suele darte Opus o WebM: tendrás que manejar la conversión o usar el camino WebRTC que lo hace por ti.

Expiración de token en sesiones largas

Los tokens efímeros son de corta duración. Si pruebas una sesión más larga que el TTL del token, renueva según un calendario. El SDK de Realtime tiene ayudantes para esto; hacerlo a mano significa vigilar el evento session.expired y emitir un token nuevo antes de que muera el viejo.

Cómo se ve esto en producción

El único cambio real de desarrollo a producción es la URL: reemplaza el hostname del túnel por tu dominio real. El endpoint emisor de tokens se queda en tu backend. La conexión WebRTC/WebSocket del navegador a OpenAI es el mismo camino de código. Hemos visto equipos darle demasiadas vueltas e intentar hacer proxy del tráfico realtime por su backend: no lo hagas, añade latencia y rompe el modelo que asume el SDK de OpenAI.

Para la oferta paralela de Anthropic (que se parece más a un bucle de tool use que a un WebSocket en streaming), mira Anthropic tool use y webhooks en local. Únete a la lista de espera de PortPreview para un túnel que maneja los upgrades de WebSocket por defecto.

Preguntas frecuentes

¿Puedo probar la OpenAI Realtime API en localhost?
Las conexiones del lado del servidor no necesitan túnel. Las conexiones del lado del cliente desde un navegador necesitan HTTPS para los permisos de micrófono y los endpoints de tokens efímeros. Usa un túnel para exponer tu servidor de desarrollo por HTTPS y luego conecta el navegador directamente a OpenAI con el token efímero.
¿Mi túnel necesita soportar WebSockets para la Realtime API?
Si usas el transporte WebSocket, sí: el túnel debe reenviar las peticiones de upgrade HTTP. La mayoría de los túneles modernos lo hacen, pero vale la pena probarlo con wscat antes de perseguir un bug de conexión fantasma. WebRTC evita el túnel para el propio tráfico realtime.
¿Por qué necesito tokens efímeros para las conexiones realtime del navegador?
Poner tu API key completa en el navegador es un desastre de seguridad. Tu backend emite un token efímero de corta duración limitado a una sesión realtime. El navegador usa ese token para conectarse directamente a OpenAI sin ver nunca tu API key real.