I have a real-time chat app that uses WebRTC to connect with OpenAI’s Realtime API through a signaling server on Cloudflare Workers. Everything works great when I test it locally, but once I deploy it to production the WebRTC connection just fails and goes to a failed state.
Here’s what happens:
- Browser creates SDP offer and sends to /connect-rtc endpoint
- Worker forwards the offer to OpenAI API
- Browser tries to set remote description and exchange ICE candidates
Client side code:
connection = new RTCPeerConnection();
responseChannel = connection.createDataChannel('messages');
connection.createOffer().then((sdpOffer) => {
connection.setLocalDescription(sdpOffer);
fetch('/connect-rtc', {
method: 'POST',
body: sdpOffer.sdp,
headers: {
'Content-Type': 'application/sdp',
},
})
.then((response) => response.text())
.then((sdpAnswer) => {
connection.setRemoteDescription({
sdp: sdpAnswer,
type: 'answer',
});
})
.catch((err) => console.error("Signaling failed:", err));
});
Server endpoint:
router.post('/connect-rtc', async (context) => {
const requestBody = await context.req.text();
const apiUrl = new URL('https://api.openai.com/v1/realtime');
apiUrl.searchParams.set('model', 'gpt-4o-realtime-preview-2024-12-17');
apiUrl.searchParams.set('instructions', SYSTEM_PROMPT);
apiUrl.searchParams.set('voice', 'nova');
const apiResponse = await fetch(apiUrl.toString(), {
method: 'POST',
body: requestBody,
headers: {
Authorization: `Bearer ${context.env.OPENAI_API_KEY}`,
'Content-Type': 'application/sdp',
},
});
if (!apiResponse.ok) {
const errorMsg = await apiResponse.text();
console.error('API Error:', errorMsg);
return context.text(errorMsg, 500);
}
const answerSdp = await apiResponse.text();
console.log('Received SDP Answer:', answerSdp);
return context.body(answerSdp, {
headers: {
'Content-Type': 'application/sdp',
},
});
});
Any ideas what could be causing this production vs local difference?