L'API Realtime d'OpenAI connecte les clients en WebSocket ou WebRTC. Côté serveur, n'importe quelle machine avec internet suffit. Côté client — ce que vous voulez construire la plupart du temps — le navigateur a besoin d'un origin sécurisé et votre backend doit générer des tokens éphémères. Les deux passent par un tunnel. Quelques détails à connaître.
Deux modes de connexion, deux raisons de tunneliser
Connexion côté serveur : votre backend ouvre un WebSocket vers OpenAI. Pas de tunnel nécessaire. Connexion côté client : un navigateur ouvre WebRTC ou WebSocket avec un token éphémère minté par votre backend. Presque toujours besoin d'un tunnel.
Pourquoi HTTPS côté client :
- Permissions micro navigateur nécessitent un origin sécurisé.
getUserMediaet ICE WebRTC fonctionnent mieux en HTTPS.- Service workers en exigent.
- Si front en HTTPS, backend appelé pour le token doit aussi être HTTPS.
Vous pouvez contourner avec des flags navigateur. Ne faites pas ça. Utilisez un tunnel.
Anatomie d'une app realtime en dev
- Un front qui capture le micro et joue l'audio.
- Une route backend qui mint un token éphémère via
/v1/realtime/sessionsavec votre vraie clé API. - Une connexion WebRTC ou WebSocket directe du navigateur vers OpenAI avec le token éphémère.
Le tunnel expose front + backend. Le trafic realtime va directement navigateur-OpenAI, pas via le tunnel.
Setup avec PortPreview
- Lancez votre dev server (port 3000 ou 5173).
- Exécutez
npx portpreview 3000. - Ouvrez l'URL HTTPS. Les permissions micro fonctionnent.
- Appelez l'endpoint qui mint le token, ouvrez la connexion realtime.
- Parlez, recevez une réponse streamée.
Avec Vite, voir Vite + tunnel pour allowedHosts et HMR. Avec Next.js, attention au runtime edge sur les routes nécessitant crypto Node.
WebSocket upgrades à travers les tunnels
Les connexions realtime sont WebSocket (ou WebRTC qui shunte le tunnel). Le tunnel doit forwarder le Upgrade. PortPreview, Cloudflare quick tunnels, ngrok le font. Sinon, échec silencieux côté navigateur avec un WebSocket closed before connected sans détail utile.
Testez avec wscat en cas de doute.
Astuces de debug
Inspecter la requête de mint
Bug fréquent : mauvais modèle, voix ou modalités dans la requête vers /v1/realtime/sessions. Le tunnel capture front→backend, pas backend→OpenAI. Loggez côté serveur.
Formats audio
Realtime utilise PCM16 par défaut. MediaRecorder navigateur donne Opus ou WebM — conversion nécessaire, ou utilisez WebRTC qui s'en charge.
Expiration de token
Tokens éphémères courts. Pour les longues sessions, rafraîchissez sur planning. Le SDK Realtime a des helpers ; sinon, écoutez session.expired et mint avant expiration.
Production
Seul changement de dev à prod : l'URL. L'endpoint de mint reste backend. La connexion realtime reste browser-to-OpenAI.
Pour Anthropic (plus proche d'une boucle tool-use que d'un streaming), voir Anthropic tool use en local. Rejoignez la waitlist PortPreview.