OpenAI Realtime API соединяет клиентов по WebSocket или WebRTC. Для серверных соединений можно обращаться к OpenAI напрямую с любой машины с интернетом. Для клиентских соединений — а это большая часть того, что вы реально захотите построить, — браузеру нужен защищённый origin, а ваш бэкенд должен выпускать эфемерные токены. И то, и другое работает через туннель. Несколько деталей стоит знать.
Два способа подключения, две причины туннелировать
Realtime API поддерживает серверные соединения (ваш бэкенд открывает WebSocket к OpenAI) и клиентские (браузер открывает WebRTC-peer-соединение или WebSocket, используя эфемерный токен, выпущенный вашим бэкендом). Серверный путь не требует туннеля. Клиентский — почти всегда требует.
Почему клиентской стороне нужен HTTPS:
- Разрешения микрофона в браузере требуют защищённого origin.
getUserMediaи обработка ICE в WebRTC лучше всего работают по HTTPS.- Service worker'ам (если они есть) это нужно.
- Если вы вызываете эндпоинт
/sessionбэкенда за эфемерным токеном, этот бэкенд тоже должен быть на HTTPS, если фронтенд на HTTPS.
Первый пункт можно обойти флагами браузера. Не надо. Возьмите туннель и живите в реальном мире.
Структура Realtime-приложения в разработке
Минимальное realtime-приложение состоит из трёх частей:
- Фронтенд, захватывающий вход микрофона и проигрывающий аудиовыход.
- Бэкенд-маршрут, выпускающий эфемерный токен обращением к эндпоинту OpenAI
/v1/realtime/sessionsс вашим настоящим API-ключом. - Прямое WebRTC- или WebSocket-соединение из браузера к OpenAI с эфемерным токеном.
Туннель открывает фронтенд + бэкенд (в большинстве сетапов один домен). Сам realtime-трафик идёт браузер-к-OpenAI, а не через туннель — это соединение прямое по HTTPS/WSS.
Быстрая настройка с PortPreview
- Запустите dev-сервер (Next.js, Vite, что угодно) на порту 3000 или 5173.
- Выполните
npx portpreview 3000. - Откройте HTTPS-URL в браузере. Запросы разрешения микрофона работают как обычно.
- Вызовите эндпоинт выпуска токена, получите эфемерный токен, откройте realtime-соединение.
- Говорите, получайте потоковый ответ.
Если используете Vite, вам нужна конфигурация allowedHosts и HMR из Vite + туннель. На Next.js с edge runtime где-либо — следите за runtime-конфигом маршрутов, которым нужен Node-crypto.
WebSocket-upgrade через туннели
Realtime-соединения — это WebSocket (или WebRTC, который в основном минует туннель). Любой используемый туннель должен корректно пробрасывать HTTP-Upgrade-запрос. Большинство пробрасывает — PortPreview, Cloudflare quick tunnels, ngrok все обрабатывают WebSocket-upgrade. Если ваш не пробрасывает, соединение тихо падает в браузере с обобщённым WebSocket closed before connected без полезных деталей.
Проверьте upgrade с помощью wscat, если не уверены. Подключитесь к wss://your-tunnel.portpreview.dev/anything и наблюдайте за handshake.
Приёмы разработки, которые помогают
Изучите запрос выпуска токена
Ваш фронтенд вызывает бэкенд-маршрут, который вызывает OpenAI. Самый частый dev-баг здесь — неправильно сконфигурированный запрос к /v1/realtime/sessions: не то имя модели, не тот voice, не те modalities. Туннель захватывает запрос фронтенд-к-бэкенду, но не хоп бэкенд-к-OpenAI. Логируйте этот запрос на сервере или проксируйте через туннель, запустив оба слоя локально.
Несовпадения аудиоформата
Realtime API по умолчанию использует PCM16 с настраиваемой частотой дискретизации. Если вы подаёте аудио другого формата, модель либо отвергнет, либо начнёт галлюцинировать. Браузерный MediaRecorder обычно даёт Opus или WebM — вам нужно обрабатывать конвертацию или использовать путь WebRTC, который делает это за вас.
Истечение токена в долгих сессиях
Эфемерные токены недолговечны. Если тестируете сессию длиннее TTL токена, обновляйте по расписанию. У Realtime SDK есть хелперы для этого; делая вручную, следите за событием session.expired и выпускайте новый токен до смерти старого.
Как это выглядит в продакшене
Единственное реальное изменение от разработки к продакшену — URL: замените хостнейм туннеля на ваш настоящий домен. Эндпоинт выпуска токена остаётся на бэкенде. WebRTC/WebSocket-соединение браузер-к-OpenAI — тот же путь кода. Мы видели, как команды переусложняют это и пытаются проксировать realtime-трафик через бэкенд — не надо, это добавляет задержку и ломает модель, которую предполагает SDK OpenAI.
Про параллельное предложение Anthropic (которое ближе к циклу tool use, чем к стриминговому WebSocket) см. Anthropic tool use и вебхуки локально. Присоединяйтесь к листу ожидания PortPreview ради туннеля, который по умолчанию обрабатывает WebSocket-upgrade.