From fa1b892c78a7ee42a8934c2321f34b2f5cb4c0ba Mon Sep 17 00:00:00 2001 From: Craig Dennis Date: Tue, 4 Feb 2025 22:33:29 -0800 Subject: [PATCH] Moves to use ephemeral tokens --- public/script.js | 40 ++++++++++++++++++++++++---------------- src/index.ts | 40 +++++++++++++++++----------------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/public/script.js b/public/script.js index 1a0b7d6..f82db03 100644 --- a/public/script.js +++ b/public/script.js @@ -36,7 +36,7 @@ peerConnection.ontrack = (event) => { document.body.appendChild(el); }; -const dataChannel = peerConnection.createDataChannel('response'); +const dataChannel = peerConnection.createDataChannel('oai-events'); function configureData() { console.log('Configuring data channel'); @@ -137,22 +137,30 @@ navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => { peerConnection.createOffer().then((offer) => { peerConnection.setLocalDescription(offer); + fetch('/session') + .then((tokenResponse) => tokenResponse.json()) + .then((data) => { + const EPHEMERAL_KEY = data.result.client_secret.value; + const baseUrl = 'https://api.openai.com/v1/realtime'; + const model = 'gpt-4o-realtime-preview-2024-12-17'; + fetch(`${baseUrl}?model=${model}`, { + method: 'POST', + body: offer.sdp, + headers: { + Authorization: `Bearer ${EPHEMERAL_KEY}`, + 'Content-Type': 'application/sdp', + }, + }) + .then((r) => r.text()) + .then((answer) => { + // Accept answer from Realtime WebRTC API + peerConnection.setRemoteDescription({ + sdp: answer, + type: 'answer', + }); + }); + }); // Send WebRTC Offer to Workers Realtime WebRTC API Relay - fetch('/rtc-connect', { - method: 'POST', - body: offer.sdp, - headers: { - 'Content-Type': 'application/sdp', - }, - }) - .then((r) => r.text()) - .then((answer) => { - // Accept answer from Realtime WebRTC API - peerConnection.setRemoteDescription({ - sdp: answer, - type: 'answer', - }); - }); }); }); diff --git a/src/index.ts b/src/index.ts index daffba6..71a780e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,37 +1,31 @@ import { Hono } from 'hono'; +import { cors } from 'hono/cors'; const app = new Hono<{ Bindings: Env }>(); +app.use(cors()); const DEFAULT_INSTRUCTIONS = `You are helpful and have some tools installed. In the tools you have the ability to control a robot hand. `; -app.post('/rtc-connect', async (c) => { - const body = await c.req.text(); - const url = new URL('https://api.openai.com/v1/realtime'); - url.searchParams.set('model', 'gpt-4o-realtime-preview-2024-12-17'); - url.searchParams.set('instructions', DEFAULT_INSTRUCTIONS); - url.searchParams.set('voice', 'ash'); - - const response = await fetch(url.toString(), { - method: 'POST', - body, +// Learn more: https://platform.openai.com/docs/api-reference/realtime-sessions/create +app.get('/session', async (c) => { + const response = await fetch("https://api.openai.com/v1/realtime/sessions", { + method: "POST", headers: { - Authorization: `Bearer ${c.env.OPENAI_API_KEY}`, - 'Content-Type': 'application/sdp', + "Authorization": `Bearer ${c.env.OPENAI_API_KEY}`, + "Content-Type": "application/json", }, - }); - - if (!response.ok) { - throw new Error(`OpenAI API error: ${response.status}`); - } - const sdp = await response.text(); - return c.body(sdp, { - headers: { - 'Content-Type': 'application/sdp', - }, - }); + body: JSON.stringify({ + model: "gpt-4o-realtime-preview-2024-12-17", + instructions: DEFAULT_INSTRUCTIONS, + voice: "ash", + }), + }); + const result = await response.json(); + return c.json({result}); }); + export default app;