9-realtime/openai-realtime-console-example/relay-server/lib/relay.js (69 lines of code) (raw):

import { WebSocketServer } from 'ws'; import { RealtimeClient } from '@openai/realtime-api-beta'; export class RealtimeRelay { constructor(apiKey) { this.apiKey = apiKey; this.sockets = new WeakMap(); this.wss = null; } listen(port) { this.wss = new WebSocketServer({ port }); this.wss.on('connection', this.connectionHandler.bind(this)); this.log(`Listening on ws://localhost:${port}`); } async connectionHandler(ws, req) { if (!req.url) { this.log('No URL provided, closing connection.'); ws.close(); return; } const url = new URL(req.url, `http://${req.headers.host}`); const pathname = url.pathname; if (pathname !== '/') { this.log(`Invalid pathname: "${pathname}"`); ws.close(); return; } // Instantiate new client this.log(`Connecting with key "${this.apiKey.slice(0, 3)}..."`); const client = new RealtimeClient({ apiKey: this.apiKey }); // Relay: OpenAI Realtime API Event -> Browser Event client.realtime.on('server.*', (event) => { this.log(`Relaying "${event.type}" to Client`); ws.send(JSON.stringify(event)); }); client.realtime.on('close', () => ws.close()); // Relay: Browser Event -> OpenAI Realtime API Event // We need to queue data waiting for the OpenAI connection const messageQueue = []; const messageHandler = (data) => { try { const event = JSON.parse(data); this.log(`Relaying "${event.type}" to OpenAI`); client.realtime.send(event.type, event); } catch (e) { console.error(e.message); this.log(`Error parsing event from client: ${data}`); } }; ws.on('message', (data) => { if (!client.isConnected()) { messageQueue.push(data); } else { messageHandler(data); } }); ws.on('close', () => client.disconnect()); // Connect to OpenAI Realtime API try { this.log(`Connecting to OpenAI...`); await client.connect(); } catch (e) { this.log(`Error connecting to OpenAI: ${e.message}`); ws.close(); return; } this.log(`Connected to OpenAI successfully!`); while (messageQueue.length) { messageHandler(messageQueue.shift()); } } log(...args) { console.log(`[RealtimeRelay]`, ...args); } }