OpenAI Realtime API เชื่อมต่อไคลเอนต์ผ่าน WebSocket หรือ WebRTC สำหรับการเชื่อมต่อฝั่งเซิร์ฟเวอร์ คุณเข้าถึง OpenAI ได้โดยตรงจากเครื่องใดก็ตามที่มีอินเทอร์เน็ต สำหรับการเชื่อมต่อฝั่งไคลเอนต์ — ซึ่งคือสิ่งที่คุณอยากสร้างด้วยมันจริงๆ เป็นส่วนใหญ่ — เบราว์เซอร์ต้องการ origin ที่ปลอดภัย และ backend ของคุณต้องสร้างโทเค็นชั่วคราว ทั้งสองทำงานผ่านทันเนล มีรายละเอียดบางอย่างที่ควรรู้
สองวิธีในการเชื่อมต่อ สองเหตุผลในการทันเนล
Realtime API รองรับการเชื่อมต่อฝั่งเซิร์ฟเวอร์ (backend ของคุณเปิด WebSocket ไปยัง OpenAI) และการเชื่อมต่อฝั่งไคลเอนต์ (เบราว์เซอร์เปิดการเชื่อมต่อ peer WebRTC หรือ WebSocket โดยใช้โทเค็นชั่วคราวที่ backend ของคุณสร้าง) เส้นทางฝั่งเซิร์ฟเวอร์ไม่ต้องการทันเนล ฝั่งไคลเอนต์เกือบทุกครั้งต้องการ
ทำไมฝั่งไคลเอนต์จึงต้องการ HTTPS:
- สิทธิ์ไมโครโฟนของเบราว์เซอร์ต้องการ origin ที่ปลอดภัย
getUserMediaและการจัดการ ICE ของ WebRTC ทำงานดีที่สุดบน HTTPS- service worker (ถ้ามี) ต้องการมัน
- หากคุณเรียก endpoint
/sessionของ backend เพื่อรับโทเค็นชั่วคราว backend นั้นก็ต้องเป็น HTTPS ด้วยหาก frontend ของคุณเป็น
ข้อแรกคุณเลี่ยงได้ด้วย flag ของเบราว์เซอร์ อย่าทำ ใช้ ทันเนล แล้วอยู่ในโลกจริง
รูปร่างของแอป Realtime ในช่วงพัฒนา
แอป realtime ขั้นต่ำมีสามส่วน:
- frontend ที่จับอินพุตไมโครโฟนและเล่นเอาต์พุตเสียง
- route ของ backend ที่สร้างโทเค็นชั่วคราวโดยเรียก endpoint
/v1/realtime/sessionsของ OpenAI ด้วย API key จริงของคุณ - การเชื่อมต่อ WebRTC หรือ WebSocket โดยตรงจากเบราว์เซอร์ไปยัง OpenAI โดยใช้โทเค็นชั่วคราว
ทันเนลของคุณเปิด frontend + backend (โดเมนเดียวกันในการตั้งค่าส่วนใหญ่) ทราฟฟิก realtime จริงไปจากเบราว์เซอร์-ถึง-OpenAI ไม่ผ่านทันเนลของคุณ — การเชื่อมต่อนั้นเป็นแบบตรงผ่าน HTTPS/WSS
ตั้งค่าอย่างรวดเร็วด้วย PortPreview
- เริ่ม dev server (Next.js, Vite หรืออะไรก็ตาม) บนพอร์ต 3000 หรือ 5173
- รัน
npx portpreview 3000 - เปิด URL HTTPS ในเบราว์เซอร์ คำขอสิทธิ์ไมโครโฟนทำงานตามปกติ
- เรียก endpoint สร้างโทเค็น รับโทเค็นชั่วคราว เปิดการเชื่อมต่อ realtime
- พูด รับการตอบกลับแบบสตรีม
หากใช้ Vite คุณจะต้องใช้ config allowedHosts และ HMR จาก Vite + ทันเนล หากใช้ Next.js ที่มี edge runtime ที่ไหนสักแห่ง ระวัง config runtime บน route ที่ต้องใช้ 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
เคล็ดลับการพัฒนาที่ช่วยได้
ตรวจคำขอสร้างโทเค็น
frontend ของคุณเรียก route ของ backend ที่เรียก OpenAI บั๊กการพัฒนาที่พบบ่อยที่สุดตรงนี้คือคำขอที่ตั้งค่าผิดไปยัง /v1/realtime/sessions — ชื่อโมเดลผิด voice ผิด modalities ผิด ทันเนลจับคำขอ frontend→backend แต่ไม่จับ hop backend→OpenAI ให้ log คำขอนั้นฝั่งเซิร์ฟเวอร์ หรือ proxy ผ่านทันเนลโดยรันทั้งสองชั้นบนเครื่องโลคัล
รูปแบบเสียงไม่ตรงกัน
Realtime API ใช้ PCM16 โดยค่าเริ่มต้นพร้อม sample rate ที่ตั้งได้ หากคุณป้อนเสียงจากรูปแบบอื่น โมเดลจะปฏิเสธหรือ hallucinate MediaRecorder ของเบราว์เซอร์มักให้ Opus หรือ WebM — คุณต้องจัดการการแปลง หรือใช้เส้นทาง WebRTC ที่จัดการให้คุณ
โทเค็นหมดอายุระหว่างเซสชันยาว
โทเค็นชั่วคราวมีอายุสั้น หากคุณทดสอบเซสชันที่ยาวกว่า TTL ของโทเค็น ให้รีเฟรชตามตาราง SDK ของ Realtime มี helper สำหรับสิ่งนี้ หากทำเอง หมายถึงคอยดูเหตุการณ์ session.expired และสร้างโทเค็นใหม่ก่อนที่ตัวเก่าจะตาย
หน้าตาในโปรดักชัน
การเปลี่ยนแปลงจริงเพียงอย่างเดียวจากพัฒนาสู่โปรดักชันคือ URL: แทนที่ hostname ของทันเนลด้วยโดเมนจริงของคุณ endpoint สร้างโทเค็นอยู่ที่ backend การเชื่อมต่อ WebRTC/WebSocket จากเบราว์เซอร์ไป OpenAI เป็น code path เดียวกัน เราเคยเห็นทีมคิดมากเกินไปแล้วพยายาม proxy ทราฟฟิก realtime ผ่าน backend — อย่าทำ มันเพิ่ม latency และทำลายโมเดลที่ SDK ของ OpenAI สมมติไว้
สำหรับข้อเสนอคู่ขนานของ Anthropic (ซึ่งใกล้กับลูป tool use มากกว่า WebSocket แบบสตรีม) ดู Anthropic tool use และ webhook บนเครื่องโลคัล เข้าร่วม waitlist ของ PortPreview สำหรับทันเนลที่จัดการ WebSocket upgrade โดยค่าเริ่มต้น