Усі статті
OpenAIRealtime APIWebSocketAI

Тестування OpenAI Realtime API локально через тунель

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-застосунок складається з трьох частин:

  1. Фронтенд, що захоплює вхід мікрофона й відтворює аудіовихід.
  2. Маршрут бекенду, що видає ефемерний токен зверненням до ендпоінту OpenAI /v1/realtime/sessions з вашим справжнім API-ключем.
  3. Пряме WebRTC- або WebSocket-з'єднання з браузера до OpenAI з ефемерним токеном.

Тунель відкриває фронтенд + бекенд (у більшості налаштувань один домен). Сам realtime-трафік іде браузер-до-OpenAI, а не через тунель — це з'єднання пряме по HTTPS/WSS.

Швидке налаштування з PortPreview

  1. Запустіть dev-сервер (Next.js, Vite, будь-що) на порту 3000 або 5173.
  2. Виконайте npx portpreview 3000.
  3. Відкрийте HTTPS-URL у браузері. Запити дозволу мікрофона працюють як звичайно.
  4. Викличте ендпоінт видачі токена, отримайте ефемерний токен, відкрийте realtime-з'єднання.
  5. Говоріть, отримуйте потокову відповідь.

Якщо використовуєте 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.

Поширені запитання

Чи можна тестувати OpenAI Realtime API на localhost?
Серверні з'єднання не потребують тунелю. Клієнтські з'єднання з браузера потребують HTTPS для дозволів мікрофона та ендпоінтів ефемерних токенів. Використовуйте тунель, щоб відкрити dev-сервер по HTTPS, потім під'єднайте браузер до OpenAI напряму з ефемерним токеном.
Чи має тунель підтримувати WebSocket для Realtime API?
Якщо використовуєте транспорт WebSocket — так, тунель має пробрасувати HTTP-upgrade-запити. Більшість сучасних тунелів це роблять, але варто перевірити з wscat, перш ніж ганятися за фантомним багом з'єднання. WebRTC минає тунель для самого realtime-трафіку.
Навіщо потрібні ефемерні токени для realtime-з'єднань із браузера?
Класти повний API-ключ у браузер — катастрофа безпеки. Ваш бекенд видає недовговічний ефемерний токен, обмежений однією realtime-сесією. Браузер використовує цей токен для прямого під'єднання до OpenAI, ніколи не бачачи ваш справжній API-ключ.