1 คะแนน โดย GN⁺ 4 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • WebRTC ให้ความสำคัญกับความหน่วงต่ำแบบการโทรประชุม จึงทิ้งแพ็กเก็ตเสียงอย่างมากเมื่อเครือข่ายไม่ดี แต่สำหรับ Voice AI ความเสียหายของพรอมป์ตเสียงอาจทำให้คุณภาพคำตอบแย่กว่าการตอบช้า
  • TTS สามารถสร้างเสียงได้เร็วกว่าการเล่นแบบเรียลไทม์ จึงใช้บัฟเฟอร์ฝั่งไคลเอนต์เพื่อซ่อนปัญหาเครือข่ายระยะสั้นได้ แต่ WebRTC เรนเดอร์ตามเวลาที่มาถึงและมีจิตเตอร์บัฟเฟอร์ขนาดเล็ก ทำให้ต้องหน่วงส่งแพ็กเก็ตแบบประดิษฐ์เพื่อให้มาถึงตรงเวลา
  • WebRTC มีความซับซ้อนในการตั้งค่าและการปฏิบัติการจากการใช้พอร์ตชั่วคราว, ICE, DTLS, SCTP ฯลฯ และเมื่อมัลติเพล็กซ์บนพอร์ตเดียวก็ยากที่จะ route แพ็กเก็ต STUN, SRTP/SRTCP, DTLS, TURN ไปยังแต่ละการเชื่อมต่อ
  • แม้ OpenAI จะต้องการการตั้งค่าการเชื่อมต่อที่รวดเร็ว แต่ WebRTC อาจต้องใช้ขั้นต่ำ 8 RTT เมื่อรวมขั้นตอน signaling และ media server และเพราะโครงสร้างที่รองรับ P2P แม้เซิร์ฟเวอร์จะมี IP คงที่ก็ยังต้องผ่านขั้นตอนเดียวกัน
  • ทางเลือกที่เสนอคือ WebSockets และ QUIC/WebTransport โดย QUIC รองรับพอร์ตเดียว, การเปลี่ยนที่อยู่, load balancing แบบไร้สถานะ, และการผสม anycast กับ unicast ได้ง่ายกว่าผ่าน CONNECTION_ID, QUIC-LB และ preferred_address

ทำไม WebRTC จึงไม่เหมาะกับ Voice AI

  • WebRTC ถูกออกแบบมาสำหรับการสนทนาโต้ตอบรวดเร็วแบบการโทรประชุม จึง ทิ้งแพ็กเก็ตเสียงอย่างหนักเพื่อรักษาความหน่วงให้ต่ำ เมื่อสภาพเครือข่ายไม่ดี
  • สำหรับ Voice AI การให้พรอมป์ตถูกส่งอย่างแม่นยำสำคัญกว่า แม้ผู้ใช้จะต้องรอคำตอบช้าลงเล็กน้อยก็ตาม
    • ตัวอย่างเช่น หากพรอมป์ตเสียงอย่าง “จะเดินไปที่ร้านล้างรถหรือจะขับรถไป” เสียหาย คุณภาพของคำตอบหลังจากนั้นก็อาจแย่ลงได้
  • การทำงานของเสียง WebRTC ในเบราว์เซอร์ตั้งอยู่บนสมมติฐานเรื่องความหน่วงแบบเรียลไทม์อย่างมาก และเมื่อ Discord เคยทดลองก็พบว่าไม่สามารถ retransmit แพ็กเก็ตเสียงของ WebRTC ได้
    • ภายหลังมีการอัปเดตที่ทำให้บางคนในฝั่ง WebRTC มองว่าอาจเปิดใช้ audio NACK ได้ แต่ Discord ก็ยังหาวิธีจัดการ SDP ให้ถูกต้องไม่พบ และยังติดข้อจำกัดเรื่องจิตเตอร์บัฟเฟอร์ของ WebRTC ที่เล็กมาก
  • ต่อให้ในอนาคตเอเจนต์ Voice AI จะไปถึงระดับความหน่วงแบบการสนทนาได้ การลดความหน่วงก็ยังมี trade-off และก็ยังไม่แน่ชัดว่าการยอมลดทอนคุณภาพพรอมป์ตเสียงโดยตั้งใจจะคุ้มค่าหรือไม่

ปัญหาการบัฟเฟอร์ระหว่าง TTS กับ WebRTC

  • ระบบแปลงข้อความเป็นเสียง (TTS) สามารถสร้างเสียงได้เร็วกว่าการเล่นแบบเรียลไทม์
    • ตัวอย่างเช่น หาก GPU ใช้เวลา 2 วินาทีเพื่อสร้างเสียงยาว 8 วินาที ตามอุดมคติแล้วระบบสามารถสตรีมเสียงระหว่าง 2 วินาทีที่กำลังสร้าง และให้ไคลเอนต์เล่นต่อเนื่อง 8 วินาทีพร้อมสะสมบัฟเฟอร์ในเครื่องได้
    • แบบนี้แม้จะเกิดปัญหาเครือข่ายช่วงสั้น ผู้ใช้ก็อาจไม่ทันสังเกต
  • WebRTC ไม่เข้ากับรูปแบบนี้
    • WebRTC ไม่มีการบัฟเฟอร์และเรนเดอร์ตามเวลาที่มาถึง โดยมองว่า timestamp ไม่ใช่เกณฑ์การเล่นที่เคร่งครัด
    • หากมีวิดีโอรวมอยู่ด้วย ปัญหาจะยิ่งซับซ้อนขึ้น
  • บริการอย่าง OpenAI จึงต้องหน่วงก่อนส่งแพ็กเก็ตเสียงแต่ละแพ็กเก็ตแบบประดิษฐ์ เพื่อให้มันมาถึงในจังหวะที่ควรถูกเล่นพอดี
    • หากเกิดความแออัดของเครือข่าย แพ็กเก็ตเสียงนั้นก็จะสูญหายและไม่ถูกส่งซ้ำ
  • ผลลัพธ์คือโครงสร้างที่ใส่ความหน่วงแบบประดิษฐ์เข้าไปก่อน แล้วค่อยทิ้งแพ็กเก็ตอย่างหนักเพื่อรักษา “ความหน่วงต่ำ” ซึ่งคล้ายกับการเอาวิดีโอ YouTube มาแสดงผ่านการแชร์หน้าจอโดยไม่บัฟเฟอร์
  • WebRTC มีจิตเตอร์บัฟเฟอร์สำหรับเสียงที่ปรับแบบไดนามิกตั้งแต่ 20ms ถึง 200ms ซึ่งมีไว้เพื่อลดผลกระทบจาก network jitter แต่หากส่งได้เร็วกว่าการเล่นแบบเรียลไทม์ก็อาจไม่จำเป็น

ข้อจำกัดของพอร์ตและการระบุการเชื่อมต่อ

  • โดยทั่วไปเซิร์ฟเวอร์ TCP จะเปิดพอร์ตอย่าง 443 แล้วรับการเชื่อมต่อ โดยการเชื่อมต่อจะถูกระบุจากชุดของ source/destination IP และพอร์ต
    • ตัวอย่าง: 123.45.67.89:54321 -> 192.168.1.2:443
  • หากมือถือสลับจาก WiFi ไปเครือข่ายเซลลูลาร์ หรือ NAT เปลี่ยน source IP/port การเชื่อมต่อ TCP จะขาดและต้องเชื่อมใหม่
    • TCP และ TLS handshake ใช้เวลาอย่างน้อย 2~3 RTT และสำหรับไลฟ์สตรีม ผู้ใช้อาจรู้สึกถึงการหลุดของเครือข่าย
  • WebRTC พยายามแก้ปัญหานี้ด้วยการสมมติว่าจะจัดสรรพอร์ตปลายทางชั่วคราวให้แต่ละการเชื่อมต่อ
    • หากระบุเซสชันด้วย destination IP/port อย่างเดียว ก็ยังมองว่าเป็นผู้ใช้เดิมได้แม้ source IP/port จะเปลี่ยน
  • แต่เมื่อประกอบกับสถาปัตยกรรมของ OpenAI วิธีนี้กลายเป็นปัญหาเมื่อขยายระบบขนาดใหญ่
    • จำนวนพอร์ตที่เซิร์ฟเวอร์ใช้ได้มีขีดจำกัด
    • ไฟร์วอลล์มักบล็อกพอร์ตชั่วคราว
    • และมันยังไม่ค่อยเข้ากับสภาพแวดล้อม Kubernetes

ทำไมบริการ WebRTC จึงมุ่งไปสู่การมัลติเพล็กซ์บนพอร์ตเดียว

  • หลายบริการไม่ได้ทำตามสเปก WebRTC แบบตรง ๆ แต่เลือก มัลติเพล็กซ์หลายการเชื่อมต่อบนพอร์ตเดียว
  • Twitch เคยรันเซิร์ฟเวอร์ WebRTC บน UDP:443
    • เดิม 443 เป็นพอร์ตสำหรับ HTTPS/QUIC แต่การใช้แบบนี้ช่วยให้ผ่านไฟร์วอลล์ได้มากขึ้น
    • มีการระบุว่าเครือข่ายภายในของ Amazon อนุญาตเพียงราว 30 พอร์ต
  • Discord ใช้พอร์ต 50000-50032 อย่างละหนึ่งพอร์ตต่อ CPU core
    • วิธีนี้อาจถูกบล็อกได้ง่ายกว่าในเครือข่ายภายในจำนวนมาก
  • ปัญหาใหญ่ของการมัลติเพล็กซ์บนพอร์ตเดียวคือ WebRTC เป็นโครงสร้างที่เอาหลายมาตรฐานมามัดรวมกัน
    • มีโปรโตคอลที่วิ่งบน UDP โดยตรงอยู่ 5 แบบ และแม้การแยกว่าแพ็กเก็ตเป็นของโปรโตคอลใดจะไม่ยาก แต่การ route แต่ละแพ็กเก็ตไปยังการเชื่อมต่อที่ถูกต้องเป็นเรื่องยาก
  • ความยากในการ route ตามโปรโตคอล

    • STUN
      • สามารถเลือก ufrag ที่ไม่ซ้ำกันแล้ว route ตามนั้นได้
    • SRTP/SRTCP
      • เบราว์เซอร์จะเลือกค่า ssrc แบบสุ่ม ซึ่งปกติใช้ route ได้
    • DTLS
      • อยู่ในสถานการณ์ที่ต้องคาดหวังการรองรับอย่างกว้างขวางของ RFC9146
    • TURN
      • ผู้เขียนระบุว่าไม่มีประสบการณ์ในการ implement
    • OpenAI ระบุว่าพาร์สเฉพาะ STUN แล้วหลังจากนั้นจัดการ DTLS, RTP, RTCP แบบ opaque ด้วยสถานะที่แคชไว้
    • สิ่งนี้ตีความได้ว่าเป็นโครงสร้างที่คาดหวังว่า source IP/port ของผู้ใช้จะไม่เปลี่ยน
    • เบราว์เซอร์อาจสุ่มสร้าง ssrc เดียวกันได้
    • หากเกิดการชนกันและไม่มี mapping ของ source IP/port Discord ระบุว่าใช้วิธีลองถอดรหัสแพ็กเก็ตด้วยคีย์ถอดรหัสที่เป็นไปได้แต่ละตัวเพื่อหาว่าคีย์ไหนถูกต้อง แล้วจึงระบุการเชื่อมต่อนั้น

ความหน่วงรอบไปกลับในการตั้งค่าการเชื่อมต่อ WebRTC

  • OpenAI ระบุว่า “การตั้งค่าการเชื่อมต่อที่รวดเร็วเพื่อให้ผู้ใช้พูดได้ทันทีเมื่อเซสชันเริ่ม” เป็นหนึ่งในข้อกำหนด แต่การตั้งค่า WebRTC ถูกมองว่าต้องใช้ขั้นต่ำ 8 RTT
  • ตัวอย่าง signaling server

    • หากใช้ signaling server อย่าง WHIP จะต้องมีรอบไปกลับดังนี้
      • 1 RTT สำหรับ TCP
      • 1 RTT สำหรับ TLS 1.3
      • 1 RTT สำหรับ HTTP
  • Media server

    • 1 RTT สำหรับ ICE
    • 2 RTT สำหรับ DTLS 1.2
    • 2 RTT สำหรับ SCTP
    • บางโปรโตคอลอาจเลี่ยงได้ 0.5 RTT ด้วยการทำ pipelining ทำให้การคำนวณแบบเป๊ะ ๆ ซับซ้อน แต่โดยรวมแล้วยังต้องใช้รอบไปกลับจำนวนมาก
    • ขั้นตอนเหล่านี้เกิดจากการที่ WebRTC ต้องรองรับ P2P ดังนั้นแม้เซิร์ฟเวอร์จะมี IP คงที่ก็ยังต้องผ่านกระบวนการเดิม
    • เมื่อ signaling server และ media server รันอยู่บนโฮสต์หรือโปรเซสเดียวกัน ก็จะเกิด handshake ที่ซ้ำซ้อนและมีต้นทุนสูงสองรอบ

โครงสร้างที่ผลักให้ต้อง fork WebRTC

  • มองว่า WebRTC มีข้อจำกัดมากจนในทางปฏิบัติผลักให้เกิดการ fork โปรโตคอล
  • WebRTC ประกอบด้วย RFC ราว 45 ฉบับ และ draft ที่กลายเป็นมาตรฐานโดยพฤตินัยอย่าง TWCC และ REMB ทำให้ภาระในการ implement สูง
  • implementation ในเบราว์เซอร์ถูกครอบครองโดย Google และปรับให้เข้ากับ Google Meet จึงถูกมองว่าเป็นภัยคุกคามเชิงอัตถิภาวะต่อแอปประชุมรายอื่น
  • ยังมองด้วยว่าเหตุผลที่แอปประชุมจำนวนมากนอกเหนือจาก Google Meet พยายามชวนให้ติดตั้งแอปเนทีฟ ก็เพื่อหลีกเลี่ยงการใช้ WebRTC
  • Discord ได้ fork WebRTC อย่างหนักในไคลเอนต์เนทีฟจนไม่ implement ส่วนใหญ่ของ SDP, ICE, STUN, TURN, DTLS, SCTP, SRTP ฯลฯ แต่สำหรับเว็บไคลเอนต์ก็ยังต้อง implement ทั้งชุดอยู่ดี
  • สำหรับ OpenAI แม้จะมีเงินทุนมากพอ ก็ยังมองว่าควรแทนที่ WebRTC ด้วยวิธีอื่นที่เบราว์เซอร์รองรับ มากกว่าจะ fork มัน

ทางเลือก: WebSockets และ QUIC

  • ทางเลือกในการเริ่มต้นแทน WebRTC สำหรับ Voice AI ที่ถูกเสนอคือ WebSockets
    • สามารถใช้โครงสร้างพื้นฐาน TCP/HTTP เดิมได้
    • ไม่จำเป็นต้องสร้าง load balancer สำหรับ WebRTC แบบคัสตอม
    • และถูกมองว่าเข้ากับ Kubernetes ได้ดีและขยายระบบได้
  • Head-of-line blocking ในบริบทนี้อาจไม่ใช่ข้อเสีย แต่เป็นประสบการณ์ผู้ใช้ที่พึงประสงค์
    • ตั้งอยู่บนสมมติฐานว่าการส่งตามลำดับยังดีกว่าการที่บางส่วนของพรอมป์ตเสียงหายไป
  • หากวันหนึ่งจำเป็นต้องทิ้งบางแพ็กเก็ตหรือกำหนดลำดับความสำคัญ OpenAI ควรใช้ WebTransport แบบเดียวกับ MoQ
  • การตั้งค่าการเชื่อมต่อ QUIC ทำได้ด้วย QUIC+TLS 1 RTT จึงง่ายกว่าการทำ handshake หลายชุดของ WebRTC

ข้อดีของ QUIC Connection ID

  • QUIC เลิกใช้การ route ตาม source IP/port และใส่ CONNECTION_ID ไว้ในทุกแพ็กเก็ต
    • CONNECTION_ID มีความยาวได้ตั้งแต่ 0~20 ไบต์
    • จุดสำคัญคือผู้รับเป็นคนเลือกค่านี้
  • เซิร์ฟเวอร์ QUIC สามารถสร้าง CONNECTION_ID ที่ไม่ซ้ำให้แต่ละการเชื่อมต่อได้
    • จึงใช้พอร์ตเดียวและยังระบุการเชื่อมต่อได้แม้ source IP/port จะเปลี่ยน
    • หาก source address เปลี่ยน QUIC จะสลับไปใช้ที่อยู่ใหม่โดยอัตโนมัติโดยไม่ตัดการเชื่อมต่อเหมือน TCP
  • มองว่าแนวคิดของ RFC9146 ถูกนำมาจาก QUIC

Load balancing แบบไร้สถานะ

  • load balancer ของ OpenAI พึ่งพา สถานะร่วมกัน เหมือน load balancer จำนวนมาก
    • ต้องเก็บ mapping จาก source IP/port ไปยังเซิร์ฟเวอร์ backend
    • เนื่องจาก load balancer อาจรีสตาร์ตหรือพัง จึงต้องมีที่เก็บ mapping นี้
  • OpenAI ใช้ Redis instance เพื่อเก็บ mapping ระหว่าง source IP/port กับเซิร์ฟเวอร์ backend
    • ถูกประเมินว่าเป็นวิธีที่ง่ายและตรงไปตรงมา
  • QUIC-LB เสนอวิธีที่ง่ายกว่าโดยไม่ต้องใช้ฐานข้อมูล
    • เมื่อลูกค้าเริ่มการเชื่อมต่อ QUIC load balancer จะส่งต่อแพ็กเก็ตไปยังเซิร์ฟเวอร์ backend ปกติ
    • ระหว่างทำ handshake ให้เสร็จ เซิร์ฟเวอร์ backend จะเข้ารหัส ID ของตัวเองลงใน CONNECTION_ID
    • หลังจากนั้นทุกแพ็กเก็ต QUIC จะมี backend server ID อยู่ภายใน
  • load balancer เพียงถอดข้อมูลไม่กี่ไบต์แรกแล้วส่งต่อไปยังเซิร์ฟเวอร์ที่เกี่ยวข้อง โดยไม่ต้องมีคีย์เข้ารหัสหรือตาราง route
    • แม้เซิร์ฟเวอร์จะรีบูตก็ยังรักษาวิธีนี้ไว้ได้
  • ความไร้สถานะยังหมายถึงไม่มีสถานะส่วนกลางด้วย
    • load balancer สามารถรับทราฟฟิกจาก anycast address แบบ global และส่งต่อไปยัง backend server ที่ระบุได้ทั่วโลก
    • มีการระบุว่า Cloudflare ใช้วิธีนี้อย่างกว้างขวาง
  • AWS NLB มี QUIC load balancing ที่ใช้ QUIC-LB

การผสม anycast กับ unicast

  • ในกรณีของ OpenAI ดูเหมือนจะเป็นโครงสร้างที่จัดสรรการเชื่อมต่อไปยัง regional load balancer ซึ่งใช้งานได้จริง แต่เสนอว่า Anycast เป็นแนวทางที่ดีกว่า
  • preferred_address ของ QUIC ถูกมองว่าเป็นความสามารถสำคัญต่อการทำ load balancing
  • วิธีการทำงาน

    • backend server หลายตัวทั่วโลกประกาศ anycast address เดียวกันคือ 1.2.3.4
    • เมื่อลูกค้าเชื่อมต่อไปที่ 1.2.3.4 เราเตอร์บนอินเทอร์เน็ตจะส่งแพ็กเก็ตไปยังหนึ่งในเซิร์ฟเวอร์เหล่านั้น
    • เซิร์ฟเวอร์ QUIC แต่ละตัวอาจมี unicast address ของตัวเอง เช่น 5.6.7.8
    • anycast ใช้สำหรับ handshake ส่วนการเชื่อมต่อที่มีสถานะจะคงไว้บน unicast
  • ตัวอย่างลำดับการทำงาน

    • เซิร์ฟเวอร์รับแพ็กเก็ต QUIC ทั้งที่ 1.2.3.4 และ 5.6.7.8
    • ไคลเอนต์ส่งแพ็กเก็ต QUIC handshake ไปยัง 1.2.3.4
    • เซิร์ฟเวอร์สร้างการเชื่อมต่อ QUIC และแจ้ง preferred_address=5.6.7.8
    • หลังจากนั้นไคลเอนต์จะส่งแพ็กเก็ตไปที่ 5.6.7.8
    • หากเซิร์ฟเวอร์โหลดสูงและไม่ต้องการรับการเชื่อมต่อใหม่ ก็เพียงหยุดประกาศ 1.2.3.4
    • การเชื่อมต่อเดิมไม่หลุด เพราะอยู่บน unicast
    • anycast address จึงทำหน้าที่คล้าย health check โดยพฤตินัย
    • ในโครงสร้างนี้มองว่าไม่จำเป็นต้องมี load balancer แยกต่างหาก

ข้อจำกัดและบทสรุป

  • ยอมรับว่าวิศวกรของ OpenAI มีความสามารถสูงมาก และกำลังเผชิญแรงกดดันให้ขยายระบบขนาดใหญ่โดยทันที
  • อย่างไรก็ตาม สำหรับ Voice AI นั้น WebRTC แม้จะดูเป็นตัวเลือกที่ชัดเจน แต่กลับไม่ค่อยเหมาะกับผลิตภัณฑ์และขยายระบบได้ยาก
  • MoQ เองก็ไม่ได้เหมาะสมอย่างสมบูรณ์กับ Voice AI
    • ในเสียงแบบ 1:1 ความหมายของ cache และ fan-out จำนวนมากนั้นแทบไม่มีประโยชน์
    • ถึงอย่างนั้น ข้อสรุปก็ยังเป็นว่าควรใช้ QUIC

1 ความคิดเห็น

 
GN⁺ 4 시간 전
ความคิดเห็นจาก Hacker News
  • ผมยังไม่ได้อ่านจนจบทั้งหมด แต่คิดว่าผู้เขียนเข้าใจ จุดประสงค์ของ WebRTC ในระดับพื้นฐานนะ เขาอาจจะเป็นผู้เชี่ยวชาญจริงและก็เคยสร้าง SFU ด้วย Go/Rust ให้หลายบริษัทจริง แต่ประวัติทางเทคนิคไม่ได้การันตีว่าข้อสรุปนั้นถูกต้องเสมอไป
    ผมอาจเข้าใจผิดก็ได้ แต่ดูเหมือนเขาจะปฏิบัติต่อ STUN กับ DTLS เหมือนเป็นปัจจัยสะสมที่เชื่อมกันในปัญหาเรื่อง round-trip time ทั้งที่จริงแล้วมันเป็น องค์ประกอบที่ค่อนข้างเป็นอิสระต่อกัน อีกอย่างคือเขาใช้เวลากับประเด็นที่ว่าแพ็กเก็ต retransmit ไม่ได้มากเกินไป และพอวนย้ำแนวว่า Discord พยายามอย่างหนักแค่ไหนก็รู้สึกว่าเริ่มหลุดจากประเด็น
    RTC ใน WebRTC คือ real-time communication และบางครั้งมนุษย์ก็เกลียดเสียงที่หน่วงหรือเสียงที่ความเร็วแกว่งไปมา มากกว่าเสียงที่มีแพ็กเก็ตหายเป็นช่วง ๆ เสียอีก ที่พูดถึงตรงนี้คือเสียงพูดของคน
    ถ้าไม่อยากยอมรับ packet loss ก็ใช้โปรโตคอลที่อิง TCP แทน UDP ได้ แต่ถ้าส่งเสียงผ่าน TCP บนเครือข่ายแย่ ๆ ฝั่งรับจะเกิดอาการค้างเพราะต้องรอแพ็กเก็ตที่ถูกต้องตัวถัดไป พอแพ็กเก็ตกลับมาหลังจากหน่วงไปหลายวินาที ก็ต้องตัดสินใจว่าจะเล่นเสียงที่ค้างอยู่ด้วยความเร็วปกติ หรือเร่งเล่นเพื่อไล่ให้ทันช่องสัญญาณอื่น ซึ่งโดยทั่วไปผู้ใช้ไม่ชอบประสบการณ์แบบนั้น
    ถ้าลืม WebRTC ไปสักครู่แล้วคิดเรื่อง TCP กับ UDP สำหรับเสียง จะเห็นว่ามีเหตุผลที่ VoIP ใช้ UDP มาตั้งแต่ยุค 90

  • ถ้าจะตอบในเชิงเทคนิคก่อน ผมคิดว่าอนาคตที่ไม่ใช่ WebRTC นั้นมีอยู่ เพียงแต่ไม่แน่ใจว่าทิศทางนั้นจะตรงกับแนวของ WebTransport+WebCodecs หรือเปล่า
    คำพูดที่ว่าผู้ใช้ยอมรอเพิ่มอีก 200ms เพื่อให้ prompt ที่ช้า/แพงแม่นยำขึ้นนั้น ตรงข้ามกับ feedback ที่ผมได้รับโดยสิ้นเชิง ผู้ใช้ต้องการการตอบสนองทันที ถ้ามี latency ตอนสร้างคำตอบหรือจัดการการขัดจังหวะ ความรู้สึกแบบเวทมนตร์จะหายไป อีกอย่าง ผู้ใช้ก็ไม่ได้อยากให้ส่งเร็วกว่าความเร็วจริงด้วย ถ้าผู้ใช้ตัดบทโมเดลกลางทาง เท่ากับคุณเสียแบนด์วิดท์ไปกับการส่งเสียงยาว 3 นาทีที่ถูกเล่นไปแค่ 10 วินาที
    เรื่องที่บอกว่า TTS เร็วกว่าความเร็วจริง ตอนนี้ AI เสียงยุคใหม่/ทิศทางที่กำลังมุ่งไป กำลังออกห่างจากวิธีที่ผู้เขียนอธิบาย: https://research.nvidia.com/labs/adlr/personaplex/ คือส่งเข้าออกทีละนิดในระดับ 20ms
    ประเด็นที่อยากให้ IP/พอร์ตต้นทางของผู้ใช้ไม่เปลี่ยนนั้น รองรับได้อยู่แล้ว ถ้ามี IP ใหม่เข้ามาบน ufrag ก็จัดการได้
    เรื่องที่บอกว่าต้องใช้เวลาอย่างน้อย 8 รอบ RTT ก็ไม่ถูก: https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/
    การเลือกสตรีมเสียงผ่าน WebSocket จะทำให้เสียความสามารถอย่าง AEC และผลักความซับซ้อนไปที่ฝั่งไคลเอนต์ ความเรียบง่ายของ WebRTC ตรง flow แบบ createOffer -> setRemoteDescription นี่เองที่ทำให้คนเริ่มต้นได้ง่าย หลายคนที่ใช้ Realtime API + WebSocket ลำบากเพราะโค้ดเยอะและมีหลายอย่างที่ต้องจัดการเอง
    ถ้าให้ผมเลือก ผมอยากคงโมเดล Offer/Answer ไว้ แต่ใช้ QUIC แทน DTLS+SCTP บางทีอาจทำ RTP บน QUIC ก็ได้ ผมไม่ได้ยึดติดกับตัวโปรโตคอลมากนัก แต่ยังไม่ค่อยรู้ว่าจะกระจายโค้ดที่มี footprint ใหญ่กว่ามากไปยังไคลเอนต์หลายแบบและไคลเอนต์ของลูกค้าอย่างไร

    • แน่นอนว่าผู้ใช้ต้องการ latency ต่ำ แต่ก็อยากลดกรณีที่ LLM ฟังผิดด้วย ถ้าสามารถทำ A/B test กับการแลกระหว่าง latency กับคุณภาพ ได้ก็คงดี แต่ WebRTC ทำให้ควบคุมปุ่มปรับพวกนี้ได้ยาก
      ผมไม่ใช่ผู้เชี่ยวชาญ TTS แต่ไม่ค่อยเห็นข้อดีของการทยอยปล่อยผลลัพธ์ทีละนิด ซิลิคอนไม่ได้สนใจว่าตัวเลขเวลาจะเพิ่มเร็วแค่ไหน
      บางกรณีไคลเอนต์รู้เองว่า IP เปลี่ยนและทำ ICE renegotiation ได้ แต่บ่อยครั้งมันไม่รู้ และโดยทั่วไปก็คาดหวังให้เซิร์ฟเวอร์ตรวจจับการเปลี่ยนแปลงได้ ซึ่งในโครงสร้าง load balancer ปัจจุบันทำไม่ได้ ไม่ใช่ปัญหาใหญ่ แต่ก็น่าเสียดายเมื่อขั้นตอนที่ต้องข้ามผ่านมีมากอยู่แล้ว
      ถ้าร่างนั้นหมายความว่าเป็น 7 RTT ไม่ใช่ 8 RTT บางส่วนก็ pipeline กันได้ ตัวเลขจริงอาจต่ำกว่านั้น แต่ปัญหาจริงคือเพียงเพราะอาจมีการใช้ P2P จึงเกิดทั้ง signaling server ที่จำเป็น และ TLS handshake สองชั้น
      ที่ WebRTC ดูง่ายสำหรับนักพัฒนาใหม่ เป็นเพราะมันเป็นแอปประชุมแบบ black box แต่ในบริษัทใหญ่อย่าง OpenAI กล่องดำนี้เริ่มสร้างปัญหาที่แก้ได้ด้วย primitive ระดับต่ำกว่า
      RTP over QUIC น่าลองทดลองมาก และผมก็ยินดีช่วย ถ้ากังวลเรื่องขนาดโค้ด เบราว์เซอร์และในอนาคตอาจรวมถึง OS เองจะมีไลบรารี QUIC ให้ ถ้าขยับไปทางที่ใกล้ MoQ มากขึ้น QUIC จะจัดการ fragmentation, retransmission, congestion control ฯลฯ ให้ ทำให้แอปเล็กลงอย่างน่าตกใจ
      ข้อจำกัดใหญ่ของ RoQ/MoQ คือ QUIC ทำ congestion control แม้กระทั่งกับ datagram ด้วย จึงทำ GCC ไม่ได้ เวลาส่งจากเบราว์เซอร์คงต้องผูกกับ cubic/BBR ไปอีกพักใหญ่
    • ผมสงสัยมากว่าคุณได้รับ feedback จริง ๆ ว่าผู้ใช้ชอบคำตอบผิดที่มาตอนทันที มากกว่าคำตอบถูกที่ช้ากว่า 200ms
    • ไม่จำเป็นต้องส่งทีละ 3 นาทีหรือทีละ 20ms ก็ส่งเป็น ช่วงละประมาณ 1 วินาที ได้ การส่งทีละ 20ms ก็โง่พอ ๆ กับการส่งทีละ 10 นาที
    • ถึง WebRTC จะเป็นไลบรารีที่มากับเบราว์เซอร์ มันก็ยังซับซ้อน สำหรับการโต้ตอบเสียงแบบไคลเอนต์/เซิร์ฟเวอร์ ผมไม่เห็นเหตุผลว่าทำไมต้องใช้มัน ส่งตัวอย่างเสียงด้วยวิธีอื่น แล้วหยิบแค่ตรรกะบางส่วนของ jitter buffer มาใช้ตอน playback ก็พอ
      งานปัจจุบันของผมคือประชุมเสียง/วิดีโอและสาย 1:1 ซึ่ง ความซับซ้อนของ WebRTC นั้นมหาศาล มันช่วยให้เริ่มทำโปรดักต์ได้เร็วก็จริง แต่พอจะทำอะไรแปลก ๆ ก็แก้ยากมาก แม้จะ fork มาทำฝั่งไคลเอนต์เองก็ยังยาก
      ถ้าจะบ่นเรื่อง TURN ผมเขียนยาวได้เลย จริง ๆ แล้วทั้งชุดโปรโตคอล WebRTC เหมือนถูกออกแบบมาเพื่ออินเทอร์เน็ตที่ไม่มีอยู่จริง
      TURN ควรจัดสรร rendezvous id แทนพอร์ตชั่วคราวตอนที่ไคลเอนต์ขอ allocation จากนั้น peer ก็แค่เชื่อมต่อไปยัง TURN server ผ่าน service port แล้วขอการเชื่อมต่อสำหรับ rendezvous id นั้น โดยที่ไคลเอนต์ไม่ต้องรู้ที่อยู่ของ peer เพื่อเพิ่ม permission ด้วย ปริมาณการสื่อสารที่ต้องพึ่ง relay แบบ end-to-end จะลดลง คลัสเตอร์ขั้นสูงอาจเข้ารหัสข้อมูลลงใน id เพื่อให้ไคลเอนต์และ peer ไปเชื่อมกับ TURN server ที่ใกล้ตัวเอง แล้วให้เซิร์ฟเวอร์เชื่อมกันเอง ส่วนคลัสเตอร์ที่ไม่ซับซ้อนนักก็ต้องแชร์ IP ของ TURN server และ service port ไปพร้อมกับ id
    • ไม่จำเป็นต้องผูกการส่งหน่วยเสียงแรกกับการส่งข้อมูลสำคัญเข้าด้วยกัน นักการเมืองทีวีเก่งเรื่องนี้มาก พวกเขามีชุด วลีติดปาก ไว้ถมเวลา จนกว่าสมองจะเริ่มทำงาน แค่เติมช่องว่างเพื่อไม่ให้ system 1 ของเราสูญเสียความเชื่อมั่นในการโต้ตอบก็พอ
  • ตรงที่บอกว่า “ทำไมถึงต้องรู้ timestamp ที่แสดงจริง และมันสอดคล้องกับเวลาจริงอย่างไร” นี่แทงใจมาก ดูเหมือนไม่มีใครในคนที่สร้าง WebRTC เคยซิงก์ data stream จากคนละแหล่งให้ตรงกันในระดับ ความแม่นยำระดับมิลลิวินาที เลย
    ผมเคยทำเดโมกันสั่นวิดีโอในเบราว์เซอร์โดยใช้เว็บแคมกับโมดูล IMU แต่ latency ของเส้นทาง video->rtc->browser กับ sensor->websocket->browser ต่างกันมากและไม่คงที่ วิธีแก้ที่เห็นได้ชัดคือส่ง UTC timestamp ไปกับข้อมูลเซนเซอร์แล้วให้เบราว์เซอร์ซิงก์เอง แต่กับวิดีโอมันทำไม่ได้เพราะไม่มีฐาน UTC timestamp
    ถ้าคุณคุมทั้งสองฝั่งของ WebRTC pipe ได้ ก็อาจทำอะไรสนุก ๆ อย่างส่ง UTC timestamp ของจุดเริ่มต้น stream ได้ แต่ก็ยังแก้ jitter ในเบราว์เซอร์ไม่ได้ มันพอใช้เป็น proof of concept ได้ แต่โซลูชันทั้งหมดต้องออกแบบใหม่

  • ผมมีประสบการณ์ในสายนี้พอสมควรและก็ยื่นสิทธิบัตรไว้หลายรายการ ที่ Alexa อุปกรณ์จะเปิดการเชื่อมต่อกับเซิร์ฟเวอร์ค้างไว้ แล้วพอตรวจเจอ wake word ก็ส่งสิ่งที่แทบจะเหมือน HTTP2/SPDY ไปบนการเชื่อมต่อนั้น ทำให้เริ่ม ประมวลผล STT ได้ก่อนที่ผู้ใช้จะพูดจบ เหลือแค่ latency ของการประมวลผลช่วงท้ายไม่กี่ชิ้น
    คำตอบก็กลับมาบนการเชื่อมต่อเดียวกัน
    ในกรณีของ OpenAI การเปิด persistent connection ตลอดเวลาแบบ Alexa อาจทำได้ยากกว่า แต่ถ้าใช้ HTTP2 บนมือถือ iOS กับ Android จะช่วยดูแลการเชื่อมต่อนั้นให้แทบอัตโนมัติอยู่แล้ว
    ผู้เขียนพูดถูก ไม่จำเป็นต้องใช้โปรโตคอลแบบเรียลไทม์ และการได้รับข้อมูลครบทั้งหมดสำคัญกว่า ผู้ใช้แทบไม่สังเกต latency จนกว่าจะเกิน 500ms โดยเฉพาะในยุคมือถือที่คนส่วนใหญ่คุ้นชินกับความหน่วงในการสื่อสารแบบเรียลไทม์ระหว่างคนด้วยกันอยู่แล้ว
    ถ้าคุณทำงานที่ OpenAI หรือ Anthropic ก็ทักมาได้ ยินดีคุยรายละเอียดมากขึ้น

    • ผมคิดว่าเรากำลังโฟกัสกับ transport latency มากเกินไปจนลืมว่า pipeline ของ LLM เองก็ไม่ได้จบในทันที
      transport latency แค่ถูกบวกเพิ่มบน latency อื่นก้อนใหญ่ที่มีอยู่แล้ว
      ดังนั้นผมจึงคิดว่าเลือกโซลูชันที่ latency ต่ำที่สุดเท่าที่เป็นไปได้ เพื่อจะลด end-to-end latency ของทั้ง pipeline
      การเปรียบเทียบกับ latency เสียงของมนุษย์คุยกันไม่ค่อยตรงนัก เพราะกรณีนั้นปฏิบัติต่อมนุษย์เหมือนเป็นสิ่งที่ไม่มี latency
    • ถ้าคุณเคยประมวลผลบทสนทนาเสียงราว 6,000 รายการต่อวัน ด้วยโครงสร้าง WebRTC + STT/LLM/TTS แบบเป็นชั้น ๆ คุณจะรู้ว่าประสบการณ์ของผมไม่ตรงกับคำบอกที่ว่า 500ms เป็นความหน่วงที่ผู้ใช้จับไม่ได้
      500ms ใกล้เคียงกับค่าต่ำสุดของระบบเสียงล้ำสมัยยุคนี้แล้ว หากคุณโชคดี ไม่ประหยัดเงิน และยอมใช้เทคนิคแพง ๆ อย่าง speculative decoding กับ reasoning แม้แต่ขั้น LLM อย่างเดียวก็กินเวลา 450ms ใน voice AI เชิงพาณิชย์ ทุก ms สำคัญ และเพิ่มอีกแค่ 200~300ms คุณภาพการสนทนาก็แย่ลงมาก
      ธุรกิจของเราส่วนใหญ่ทำเสียงให้ผู้ใช้ที่ไม่ใช่สายเทคนิค เมื่อปีที่แล้วตอน latency ระหว่างเทิร์นอยู่ราว 1200~1500ms เราเจอทั้งความสับสนของผู้ใช้ การพูดแทรก การหลุดจากบทสนทนา และประสบการณ์โดยรวมที่ไม่น่าพอใจ ตอนนี้ลงมาอยู่แถว 700ms แล้ว ขึ้นกับเครื่องมือที่ต้องใช้ และเริ่มใกล้ประสบการณ์ที่โอเคพอจะเทียบกับการโต้ตอบกับคนจริงได้ เราใช้เงินไม่น้อยเพื่อพยายามลดลงอีก 100ms จากจุดนี้
      เราทำเรื่องแพงและสิ้นเปลืองอย่าง speculative LLM pass, speculative tool execution ด้วย โดยรันการอนุมาน LLM หลายชุดระหว่างที่ผู้ใช้กำลังพูด แต่ยังไม่เรียกใช้เครื่องมือแบบ non-idempotent จริง ๆ จนกว่าจะรู้ว่า pass นั้นใช้ได้ และผู้ใช้ไม่ได้พูดประเด็นสำคัญไว้ท้ายประโยค วิธีนี้ลดได้ 100~200ms การบอกว่า 500ms ไม่สำคัญ น่าจะเป็นอีก use case ที่ไม่ใช่ปฏิสัมพันธ์เสียงระหว่างคนกับ AI
      ปัญหาที่ยากจริงใน voice AI ไม่ใช่แพ็กเก็ต WebRTC ที่หล่นเป็นบางครั้ง แต่คือเสียงรบกวนพื้นหลังหนัก ๆ เสียงสะท้อน และสำเนียง การทำ AEC ที่ขัดเกลามาดี ของ WebRTC ช่วยเรื่องเสียงสะท้อนได้ไม่น้อย ผมรู้ว่ามันเป็นโปรโตคอลที่ปวดหัวมากถ้าจะทำเองในระดับ OpenAI แต่สำหรับแอปที่ไม่ได้สเกลมหึมา ก็ยังมีผู้ให้บริการเชิงพาณิชย์อย่าง Daily และโซลูชันโอเค ๆ อีกหลายตัว ปัญหาที่ต้องแก้จริงอยู่ที่อื่น แต่ถ้าเพิ่ม 500ms เข้าไปใน latency budget ของผม แอปก็ตายแน่
  • น่าเสียดายที่มีไม่กี่โปรโตคอลที่ผมไม่อยาก implement เท่า WebRTC แค่จะเปิดไคลเอนต์ง่าย ๆ ตัวเดียวก็ต้องรีบทำความเข้าใจกับ SDP, TURN/STUN, ICE candidates, offer, โปรโตคอล P2P และ handshake ซับซ้อนที่เหมือนต้องทำใหม่หมดทุกครั้ง
    แค่จินตนาการว่าจะต้องใส่ trenchcoat ที่เต็มไปด้วยชั้นของโปรโตคอลและ “best practice” ที่ไม่ได้ตั้งใจพวกนั้นกลับเข้าไปทั้งหมด ก็เหนื่อยแล้ว

    • สงสัยว่าคุณเคยทำงานกับอีเมลผ่าน Microsoft Graph API หรือเปล่า
    • หลังจาก LLM มาแล้ว ผมถึงเพิ่งสร้างการตั้งค่า WebRTC datachannel ที่ทำงานได้ด้วย aiortc เป็นครั้งแรก ก่อนหน้านั้นแทบเป็นไปไม่ได้เลย ไม่มีใครรู้ว่าต้องทำอะไรอย่างไร และก็ไม่มีตัวอย่างให้ดู มันเป็นโปรโตคอลที่แย่มากและควรหายไปได้แล้ว
    • นี่แหละเหตุผลที่ผมชอบ LiveKit และ CEO ก็โอเคด้วย
    • อยากรู้ว่าคุณทำกับแพลตฟอร์มอะไรถึงได้เจ็บปวดขนาดนั้น เสียดายที่มันน่าหงุดหงิดสำหรับคุณ
      หวังว่ามันจะดีขึ้นเรื่อย ๆ เมื่อมีทั้งสื่อการสอนและไลบรารีมากขึ้น และก็น่าทึ่งเหมือนกันที่ตอนนี้เครื่องมืออย่าง Codex ช่วยดันเรื่องพวกนี้ไปได้ค่อนข้างดีแล้ว
  • API ของเบราว์เซอร์โดยรวมมี edge case ที่ไม่ได้มีเอกสารรองรับเยอะมาก และนี่ก็ไม่ใช่ ปัญหาเฉพาะของ WebRTC

  • นี่เป็นบทความที่เอนเอียงไปข้างเดียวจนน่าหงุดหงิด แม้ WebRTC จะมีข้อจำกัดจริง แต่การ พึ่งพามาตรฐาน ทำให้ได้ความถูกต้องแม่นยำหลายอย่างและลดต้นทุนวิศวกรรมระยะยาว การที่ WebRTC ซับซ้อนไม่ได้แปลว่ามันผิด แต่มันแปลว่าสื่อแบบเรียลไทม์บนอินเทอร์เน็ตสาธารณะนั้นซับซ้อน
    เครือข่ายเป็นสิ่งที่มี state โดยธรรมชาติ NAT traversal, jitter buffer, congestion control, packet loss, state ของ codec, การเข้ารหัส, session routing ไม่ได้หายไปเพียงเพราะคุณย้ายเสียงขึ้นไปบน TCP หรือ WebSocket การทำเหมือนว่ามันหายไปไม่ใช่ความชัดเจนทางสถาปัตยกรรม แต่เป็นแค่การย้ายความซับซ้อนไปไว้ในจุดที่มองเห็นน้อยกว่า

    • ผู้เขียนอธิบายภูมิหลังของตัวเองไว้ตั้งแต่ต้นแล้ว เขาสร้าง WebRTC SFU ที่ Twitch เมื่อ 6 ปีก่อน ตอนแรกก็ใช้ Pion(Go) เหมือน OpenAI แต่ benchmark แล้วช้าเกินไปเลย fork ออกมา และสุดท้ายก็เขียนโปรโตคอลทั้งหมดใหม่เอง
      หนึ่งปีก่อน เขาก็เขียน WebRTC SFU ใหม่ด้วย Rust ที่ Discord และคุณคงเห็นรูปแบบซ้ำ ๆ อยู่
      WebRTC ประกอบด้วย RFC ราว 45 ฉบับ ที่สืบทอดมาตั้งแต่ต้นยุค 2000 และยังมีมาตรฐานพฤตินัยที่ในเชิงเทคนิคยังเป็น draft อย่าง TWCC กับ REMB ด้วย เมื่อต้อง implement ทั้งหมดนี้ มันไม่สนุกเลย
      เรียกเขาว่าเป็นผู้เชี่ยวชาญ WebRTC ที่ได้รับการยอมรับก็ได้ และเพราะแบบนั้นเขาจึงบอกว่าไม่อยากใช้ WebRTC อีกแล้ว
      เขาลองพยายามแบบกระแสหลักมามากพอแล้ว ก็น่าจะมีสิทธิ์พอที่จะมีมุมมองสวนทางไม่ใช่หรือ
    • ความเอนเอียงข้างเดียวนี่แหละกลับทำให้มันสดใหม่ เหมือน บทความที่มนุษย์เขียน มากกว่าข้อความสไตล์ AI แบบ bullet point ที่พยายามบอกว่าทุกฝ่ายก็ถูกกันหมดซึ่งมีเกลื่อนทุกวันนี้
      ผมไม่ได้มีจุดยืนเรื่องหัวข้อนี้ แต่ชอบที่ตัวบทความมีเนื้อสัมผัสแบบมนุษย์ชัดเจน
      ถ้านี่เป็นงานเขียนของ AI คงแย่มากจริง ๆ
    • “มันจะยากสักแค่ไหนกัน?” หุ่นฟางถาม
      นี่ก็ปี 2026 แล้ว แต่การประชุมทางไกลก็ยังห่วยเหมือนเดิม มีเงินเดิมพันระดับหลายพันล้านดอลลาร์ และ Zoom เองก็ทำได้แค่ระดับธรรมดา ๆ บางครั้งยังแย่พอ ๆ กับของ Microsoft ด้วยซ้ำ ผมไม่เคยเห็นการประชุมทางไกลที่ไม่ดูงุ่มง่ามและหยาบกระด้างเลย
    • QUIC ก็เป็นมาตรฐานเหมือนกัน
  • บทความยอดเยี่ยมมาก ถ้าให้รางวัลโพสต์บล็อกได้เมื่อผู้เขียนเป็นผู้เชี่ยวชาญในสาขานั้น ก็คงอยากมอบให้ชิ้นนี้

  • สำหรับประโยคที่ว่า “WebRTC ถูกออกแบบมาให้ทำให้ prompt ของผมด้อยคุณภาพและหล่นหายในสภาพเครือข่ายแย่ ๆ” ถ้าคุณต้องการความเป็นเรียลไทม์ นั่นก็เป็นสิ่งที่ต้องยอมรับ ถ้าไม่ต้องการความเป็นเรียลไทม์ และมองทุกอย่างเป็น STT -> Prompt -> TTS ก็อาจไม่จำเป็นต้องส่งเสียงผ่านเครือข่ายตั้งแต่แรกด้วยซ้ำ

    • ผมคือผู้เขียนเอง ขออภัยที่คำตอบในคอมเมนต์อาจไม่สนุกเท่าตัวบทความ
      ทุกแอปพลิเคชัน low-latency ต้องตัดสินใจเรื่อง trade-off ของประสบการณ์ผู้ใช้ระหว่างคุณภาพกับ latency ความแออัดก่อให้เกิดการเข้าคิว ซึ่งก็คือ latency และถ้าจะหลีกเลี่ยงก็ต้องข้ามบางอย่างไป ทำให้คุณภาพลดลง
      ปุ่มปรับ latency เทียบกับคุณภาพของ WebRTC ถูกล็อกตาย มันยอดเยี่ยมมากถ้าจุดประสงค์คือกด latency ให้ต่ำที่สุด แต่ขาดความยืดหยุ่น ถึงอย่างนั้นเพราะการรองรับในเบราว์เซอร์ มันก็ยังแทบเป็นหนึ่งในไม่กี่ตัวเลือกที่เหลือ ผมจึงยังตั้งใจจะใช้ WebRTC อยู่
      แต่ตอนนี้มี WebTransport แล้ว คุณสามารถสร้างพฤติกรรมคล้าย WebRTC บนโปรโตคอลทั่วไปได้ แอปพลิเคชันเลือกเองได้ว่าจะรอนานแค่ไหนก่อน drop/reset stream โดยไม่ต้องปล่อยให้มีคนตัดสินใจแทน
      ใจความของบทความคือ โดยมากผู้ใช้ต้องการการสตรีม แต่ไม่ต้องการการหล่นหาย การสตรีมอินพุต/เอาต์พุตเสียงทำได้ตามธรรมชาติอยู่แล้วโดยไม่ต้องมี WebRTC แอปพลิเคชันควรเป็นฝ่ายกำหนดว่าเมื่อไรที่แพ็กเก็ตเสียงจะถือว่าหายไปตลอดกาล จะ 50ms, 500ms หรือ 5000ms ก็ได้ ข้อโต้แย้งคือ voice AI ไม่ควรเลือกตัวเลือก 50ms
    • ประเด็นสำคัญน่าจะอยู่ที่ use case ของ OpenAI ไม่ได้ต้องการความเป็นเรียลไทม์ใช่ไหม
      ตอนที่ OpenAI ตอบกลับ มันมีเสียงส่วนใหญ่อยู่ในมือก่อนถึงเวลาที่ผู้ใช้ต้องฟังแล้ว เนื่องจากมันสร้างเสียงได้เร็วกว่าความเร็วจริง โปรโตคอลแบบเรียลไทม์ จึงไม่ใช่ตัวเลือกที่เหมาะ
    • อาจเป็นไปได้ว่าผมพลาดการตั้งค่าเพิ่มเติมสำหรับลด latency ไป แต่ดูเหมือนไคลเอนต์จะไม่อยากรับภาระ latency แบบ STT -> Prompt -> TTS ถ้าบทสนทนารู้สึก “เหมือนจริง” พอ พวกเขาก็ยินดีรับปัญหาคุณภาพที่เกิดเป็นครั้งคราว
  • เรารัน Gemini Live API อยู่บน managed WebRTC cloud mesh และมันทำงานได้ดีมาก ใช้งานมา 2 ปีแล้ว จะลอง WebSocket และจัดการ ephemeral key เองก็ได้ แต่ถ้าคุยกับคนที่รัน เอเจนต์เสียงขนาดใหญ่ ในพื้นที่นี้ จะพบว่าปัญหาหลายอย่างถูกแก้ไปมากแล้วผ่าน WebRTC, Pipecat และทรัพยากรจำนวนมากที่เทลงไปกับปัญหาที่แก้สำเร็จแล้ว
    แน่นอนว่ามันให้ความรู้สึก overkill และอาจจะเป็นแบบนั้นจริง แต่พอเชื่อมต่อได้แล้ว มันค่อนข้างมหัศจรรย์ เวลาเริ่มต้นและการบัฟเฟอร์ก็ถูกแก้มาแล้วเพื่อการเชื่อมต่อเสียงที่เร็วขึ้น: https://github.com/pipecat-ai/pipecat-examples/tree/main/ins... วิดีโอยากกว่านั้นอีก