สร้างบริการแบ็กเอนด์ที่จำเป็นสำหรับแอป WebRTC

การส่งสัญญาณคืออะไร

การส่งสัญญาณคือกระบวนการประสานงานการสื่อสาร หากต้องการให้แอป WebRTC ตั้งค่าการโทรได้ ไคลเอ็นต์ของแอปจะต้องแลกเปลี่ยนข้อมูลต่อไปนี้

  • ข้อความควบคุมเซสชันที่ใช้เพื่อเปิดหรือปิดการสื่อสาร
  • ข้อความแสดงข้อผิดพลาด
  • ข้อมูลเมตาสื่อ เช่น ตัวแปลงรหัส การตั้งค่าตัวแปลงรหัส แบนด์วิดท์ และประเภทสื่อ
  • ข้อมูลสำคัญที่ใช้เพื่อสร้างการเชื่อมต่อที่ปลอดภัย
  • ข้อมูลเครือข่าย เช่น ที่อยู่ IP และพอร์ตของโฮสต์ตามที่โลกภายนอกเห็น

กระบวนการส่งสัญญาณนี้ต้องมีวิธีให้ไคลเอ็นต์ส่งข้อความไปมา WebRTC API ไม่ได้ใช้กลไกดังกล่าว คุณต้องสร้างเอง ในบทความนี้ คุณจะได้เรียนรู้วิธีสร้างบริการส่งสัญญาณ แต่ก่อนอื่น คุณต้องทราบบริบทเล็กน้อย

เหตุใด WebRTC จึงไม่ได้กำหนดการส่งสัญญาณ

มาตรฐาน WebRTC ไม่ได้ระบุวิธีการและโปรโตคอลการส่งสัญญาณเพื่อหลีกเลี่ยงความซ้ำซ้อนและเพิ่มความเข้ากันได้กับเทคโนโลยีที่มีอยู่ แนวทางนี้อธิบายไว้ในโปรโตคอลการสร้างเซสชัน JavaScript (JSEP) ดังนี้

สถาปัตยกรรมของ JSEP ยังช่วยให้เบราว์เซอร์ไม่ต้องบันทึกสถานะ ซึ่งหมายความว่าไม่ต้องทำหน้าที่เป็นเครื่องสถานะการส่งสัญญาณ ซึ่งจะเป็นปัญหาหากข้อมูลการส่งสัญญาณสูญหายทุกครั้งที่โหลดหน้าเว็บซ้ำ แต่จะบันทึกสถานะการส่งสัญญาณไว้ในเซิร์ฟเวอร์แทนได้

แผนภาพสถาปัตยกรรม JSEP
สถาปัตยกรรม JSEP

JSEP กำหนดให้มีการแลกเปลี่ยน offer และ answer ระหว่างเพียร์ ซึ่งเป็นข้อมูลเมตาสื่อที่กล่าวถึงข้างต้น ข้อเสนอและคำตอบจะสื่อสารในรูปแบบ Session Description Protocol (SDP) ซึ่งมีลักษณะดังนี้

v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2

หากต้องการทราบว่าคำศัพท์เฉพาะทางของ SDP ทั้งหมดนี้หมายความว่าอย่างไร ดูตัวอย่างของคณะทำงานเฉพาะกิจด้านวิศวกรรมอินเทอร์เน็ต (IETF)

โปรดทราบว่า WebRTC ได้รับการออกแบบมาเพื่อให้สามารถปรับข้อเสนอหรือคำตอบก่อนที่จะตั้งค่าเป็นคำอธิบายในเครื่องหรือระยะไกลได้โดยการแก้ไขค่าในข้อความ SDP ตัวอย่างเช่น คุณสามารถใช้ฟังก์ชัน preferAudioCodec() ใน appr.tc เพื่อตั้งค่าตัวแปลงรหัสและอัตราบิตเริ่มต้นได้ การจัดการ SDP ด้วย JavaScript ค่อนข้างยาก และมีการพูดคุยกันว่า WebRTC เวอร์ชันในอนาคตควรใช้ JSON แทนหรือไม่ แต่การใช้ SDP ต่อไปก็มีข้อดีบางอย่าง

RTCPeerConnection API และการส่งสัญญาณ: Offer, Answer และ Candidate

RTCPeerConnection เป็น API ที่แอป WebRTC ใช้เพื่อสร้างการเชื่อมต่อระหว่างเพียร์ และสื่อสารเสียงและวิดีโอ

RTCPeerConnection มี 2 งานที่ต้องทำเพื่อเริ่มต้นกระบวนการนี้

  • ตรวจสอบเงื่อนไขของสื่อในพื้นที่ เช่น ความละเอียดและความสามารถของตัวแปลงรหัส นี่คือข้อมูลเมตาที่ใช้สำหรับกลไกข้อเสนอและคำตอบ
  • รับที่อยู่เครือข่ายที่มีศักยภาพสำหรับโฮสต์ของแอป ซึ่งเรียกว่าแคนดิเดต

เมื่อยืนยันข้อมูลในเครื่องนี้แล้ว จะต้องแลกเปลี่ยนข้อมูลผ่านกลไกการส่งสัญญาณกับเพียร์ระยะไกล

ลองนึกภาพว่าอลิสกำลังพยายามโทรหาอีฟ นี่คือกลไกการเสนอ/ตอบรับทั้งหมดที่มีรายละเอียดที่ซับซ้อน

  1. อลิสสร้างออบเจ็กต์ RTCPeerConnection
  2. อลิสสร้างข้อเสนอ (คำอธิบายเซสชัน SDP) ด้วยวิธี RTCPeerConnection createOffer()
  3. อลิสโทรหา setLocalDescription() พร้อมข้อเสนอของเธอ
  4. อลิซจะแปลงข้อเสนอเป็นสตริงและใช้กลไกการส่งสัญญาณเพื่อส่งข้อเสนอไปยังอีฟ
  5. อีฟโทรหา setRemoteDescription() พร้อมข้อเสนอของอลิซ เพื่อให้ RTCPeerConnection ทราบการตั้งค่าของอลิซ
  6. อีฟโทรหา createAnswer() และมีการส่งการเรียกกลับที่สำเร็จสำหรับสิ่งนี้พร้อมคำอธิบายเซสชันในเครื่อง ซึ่งก็คือคำตอบของอีฟ
  7. อีฟตั้งคำตอบเป็นคำอธิบายในพื้นที่โดยโทรหา setLocalDescription()
  8. จากนั้นอีฟจะใช้กลไกการส่งสัญญาณเพื่อส่งคำตอบที่แปลงเป็นสตริงแล้วไปยังอลิซ
  9. อลิซตั้งค่าคำตอบของอีฟเป็นคำอธิบายเซสชันระยะไกลโดยใช้ setRemoteDescription()

นอกจากนี้ Alice และ Eve ยังต้องแลกเปลี่ยนข้อมูลเครือข่ายด้วย คำว่า "การค้นหาแคนดิเดต" หมายถึงกระบวนการค้นหาอินเทอร์เฟซเครือข่ายและพอร์ตโดยใช้เฟรมเวิร์ก ICE

  1. อลิซสร้างออบเจ็กต์ RTCPeerConnection ที่มีแฮนเดิล onicecandidate
  2. ระบบจะเรียกใช้แฮนเดิลเมื่อมีแคนดิเดตเครือข่าย
  3. ในตัวแฮนเดิล Alice จะส่งข้อมูลผู้สมัครที่แปลงเป็นสตริงให้ Eve ผ่านช่องสัญญาณ
  4. เมื่ออีฟได้รับข้อความ Candidate จากอลิซ อีฟจะเรียกใช้ addIceCandidate() เพื่อเพิ่ม Candidate ลงในคำอธิบายของเพียร์ระยะไกล

JSEP รองรับการส่ง ICE Candidate ทีละรายการ ซึ่งช่วยให้ผู้โทรระบุแคนดิเดตให้กับผู้รับสายได้ทีละรายการหลังจากข้อเสนอเริ่มต้น และช่วยให้ผู้รับสายเริ่มดำเนินการกับการโทรและตั้งค่าการเชื่อมต่อได้โดยไม่ต้องรอให้แคนดิเดตทั้งหมดมาถึง

โค้ด WebRTC สำหรับการส่งสัญญาณ

ข้อมูลโค้ดต่อไปนี้คือตัวอย่างโค้ด W3C ที่สรุปกระบวนการส่งสัญญาณทั้งหมด โค้ดนี้ถือว่ามีกลไกการส่งสัญญาณบางอย่าง SignalingChannel เราจะอธิบายการส่งสัญญาณอย่างละเอียดในภายหลัง

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // send the offer to the other peer
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

หากต้องการดูขั้นตอนการเสนอ/ตอบและขั้นตอนการแลกเปลี่ยนผู้สมัครในขณะดำเนินการ ให้ไปที่ simpl.info RTCPeerConnection และดูบันทึกคอนโซลสำหรับตัวอย่างวิดีโอแชทแบบหน้าเดียว หากต้องการข้อมูลเพิ่มเติม ให้ดาวน์โหลดการทิ้งข้อมูลที่สมบูรณ์ของการส่งสัญญาณและสถิติ WebRTC จากหน้า about://webrtc-internals ใน Google Chrome หรือหน้า opera://webrtc-internals ใน Opera

การค้นหาเพียร์

นี่เป็นวิธีที่ดูดีในการถามว่า "ฉันจะหาคนคุยด้วยได้ยังไง"

สำหรับการโทร คุณมีหมายเลขโทรศัพท์และสมุดโทรศัพท์ สำหรับการวิดีโอแชทและการรับส่งข้อความออนไลน์ คุณต้องมีระบบการจัดการข้อมูลประจำตัวและการแสดงสถานะ รวมถึงวิธีให้ผู้ใช้เริ่มเซสชัน แอป WebRTC ต้องมีวิธีให้ไคลเอ็นต์ส่งสัญญาณถึงกันว่าต้องการเริ่มหรือเข้าร่วมการโทร

WebRTC ไม่ได้กำหนดกลไกการค้นหาเพียร์ และคุณไม่จำเป็นต้องไปที่ตัวเลือกในส่วนนี้ กระบวนการนี้อาจง่ายเพียงแค่ส่งอีเมลหรือข้อความที่มี URL สำหรับแอปวิดีโอแชท เช่น Talky, tawk.to และ Browser Meeting คุณจะเชิญผู้อื่นเข้าร่วมการโทรได้โดยแชร์ลิงก์ที่กำหนดเอง นักพัฒนาซอฟต์แวร์ Chris Ball ได้สร้างการทดลอง serverless-webrtc ที่น่าสนใจ ซึ่งช่วยให้ผู้เข้าร่วมการโทรผ่าน WebRTC สามารถแลกเปลี่ยนข้อมูลเมตาผ่านบริการรับส่งข้อความใดก็ได้ที่ต้องการ เช่น IM, อีเมล หรือนกพิราบ

คุณจะสร้างบริการส่งสัญญาณได้อย่างไร

ขอย้ำอีกครั้งว่ามาตรฐาน WebRTC ไม่ได้กำหนดโปรโตคอลและกลไกการส่งสัญญาณ ไม่ว่าคุณจะเลือกอะไร คุณจะต้องมีเซิร์ฟเวอร์ตัวกลางเพื่อแลกเปลี่ยนข้อความการส่งสัญญาณและข้อมูลแอประหว่างไคลเอ็นต์ น่าเสียดายที่เว็บแอปไม่สามารถตะโกนไปในอินเทอร์เน็ตว่า "ช่วยต่อสายให้ฉันกับเพื่อนหน่อย"

โชคดีที่ข้อความส่งสัญญาณมีขนาดเล็กและส่วนใหญ่จะแลกเปลี่ยนกันในช่วงเริ่มต้นการโทร ในการทดสอบกับ appr.tc สำหรับเซสชันวิดีโอแชท บริการส่งสัญญาณจะจัดการข้อความทั้งหมดประมาณ 30-45 ข้อความ โดยมีขนาดรวมของข้อความทั้งหมดประมาณ 10 KB

นอกจากจะไม่ต้องใช้แบนด์วิดท์มากนักแล้ว บริการการส่งสัญญาณ WebRTC ยังไม่ใช้การประมวลผลหรือหน่วยความจำมากนัก เนื่องจากต้องการเพียงส่งต่อข้อความและเก็บข้อมูลสถานะเซสชันจำนวนเล็กน้อย เช่น ไคลเอ็นต์ที่เชื่อมต่ออยู่

พุชข้อความจากเซิร์ฟเวอร์ไปยังไคลเอ็นต์

บริการรับส่งข้อความสำหรับการส่งสัญญาณต้องเป็นแบบ 2 ทาง ได้แก่ ไคลเอ็นต์ไปยังเซิร์ฟเวอร์และเซิร์ฟเวอร์ไปยังไคลเอ็นต์ การสื่อสารแบบ 2 ทางขัดแย้งกับโมเดลคำขอ/การตอบกลับของไคลเอ็นต์/เซิร์ฟเวอร์ HTTP แต่ก็มีการพัฒนาเทคนิคต่างๆ เช่น Long Polling มาเป็นเวลาหลายปีเพื่อส่งข้อมูลจากบริการที่ทำงานบนเว็บเซิร์ฟเวอร์ไปยังเว็บแอปที่ทำงานในเบราว์เซอร์

เมื่อเร็วๆ นี้ EventSource API ได้รับการใช้งานอย่างแพร่หลาย ซึ่งช่วยให้ใช้เหตุการณ์ที่เซิร์ฟเวอร์ส่งได้ ซึ่งเป็นข้อมูลที่ส่งจากเว็บเซิร์ฟเวอร์ไปยังไคลเอ็นต์เบราว์เซอร์ผ่าน HTTP EventSource ออกแบบมาสำหรับการรับส่งข้อความทางเดียว แต่สามารถใช้ร่วมกับ XHR เพื่อสร้างบริการสำหรับการแลกเปลี่ยนข้อความการส่งสัญญาณได้ บริการส่งสัญญาณจะส่งข้อความจากผู้โทรซึ่งส่งผ่านคำขอ XHR โดยการพุชผ่าน EventSource ไปยังผู้รับสาย

WebSocket เป็นโซลูชันที่เป็นธรรมชาติมากกว่า ออกแบบมาสำหรับการสื่อสารแบบฟูลดูเพล็กซ์ระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ ซึ่งเป็นข้อความที่สามารถไหลได้ทั้ง 2 ทิศทางพร้อมกัน ข้อดีอย่างหนึ่งของบริการส่งสัญญาณที่สร้างด้วย WebSocket หรือเหตุการณ์ที่เซิร์ฟเวอร์ส่ง (EventSource) คือแบ็กเอนด์สำหรับ API เหล่านี้สามารถติดตั้งใช้งานในเฟรมเวิร์กของเว็บต่างๆ ที่ใช้กันทั่วไปในแพ็กเกจเว็บโฮสติ้งส่วนใหญ่สำหรับภาษาต่างๆ เช่น PHP, Python และ Ruby

เบราว์เซอร์สมัยใหม่ทั้งหมด ยกเว้น Opera Mini รองรับ WebSocket และที่สำคัญกว่านั้นคือเบราว์เซอร์ทั้งหมดที่รองรับ WebRTC ก็รองรับ WebSocket ด้วย ทั้งบนเดสก์ท็อปและอุปกรณ์เคลื่อนที่ ควรใช้ TLS กับการเชื่อมต่อทั้งหมดเพื่อให้มั่นใจว่าข้อความจะไม่ถูกดักฟังโดยไม่ได้เข้ารหัส และยังช่วยลดปัญหาเกี่ยวกับการข้ามพร็อกซีด้วย (ดูข้อมูลเพิ่มเติมเกี่ยวกับ WebSocket และการข้ามพร็อกซีได้ที่บท WebRTC ในHigh Performance Browser Networking ของ Ilya Grigorik)

นอกจากนี้ยังจัดการการส่งสัญญาณได้โดยการทำให้ไคลเอ็นต์ WebRTC ทำการสำรวจเซิร์ฟเวอร์รับส่งข้อความซ้ำๆ ผ่าน Ajax แต่จะทำให้เกิดคำขอเครือข่ายที่ซ้ำซ้อนจำนวนมาก ซึ่งเป็นปัญหาอย่างยิ่งสำหรับอุปกรณ์เคลื่อนที่ แม้ว่าจะสร้างเซสชันแล้ว แต่เพียร์ก็ยังต้องสำรวจข้อความการส่งสัญญาณในกรณีที่เพียร์รายอื่นเปลี่ยนแปลงหรือสิ้นสุดเซสชัน ตัวอย่างแอป WebRTC Book ใช้ตัวเลือกนี้โดยมีการเพิ่มประสิทธิภาพบางอย่างสำหรับความถี่ในการสำรวจ

การส่งสัญญาณการปรับขนาด

แม้ว่าบริการส่งสัญญาณจะใช้แบนด์วิดท์และ CPU ต่อไคลเอ็นต์ค่อนข้างน้อย แต่เซิร์ฟเวอร์ส่งสัญญาณสำหรับแอปยอดนิยมอาจต้องจัดการข้อความจำนวนมากจากสถานที่ต่างๆ ที่มีการทำงานพร้อมกันในระดับสูง แอป WebRTC ที่มีการเข้าชมจำนวนมากต้องมีเซิร์ฟเวอร์การส่งสัญญาณที่รองรับภาระงานจำนวนมากได้ คุณไม่ต้องลงรายละเอียดที่นี่ แต่มีตัวเลือกมากมายสำหรับการรับส่งข้อความที่มีปริมาณมากและมีประสิทธิภาพสูง ซึ่งรวมถึงตัวเลือกต่อไปนี้

  • โปรโตคอลการรับส่งข้อความและการแสดงสถานะที่ขยายได้ (XMPP) เดิมเรียกว่า Jabber ซึ่งเป็นโปรโตคอลที่พัฒนาขึ้นสำหรับการรับส่งข้อความโต้ตอบแบบทันทีที่ใช้สำหรับการส่งสัญญาณได้ (การติดตั้งใช้งานเซิร์ฟเวอร์ ได้แก่ ejabberd และ Openfire ไคลเอ็นต์ JavaScript เช่น Strophe.js ใช้ BOSH เพื่อจำลองการสตรีมแบบ 2 ทาง แต่ด้วยเหตุผลต่างๆ BOSH อาจไม่มีประสิทธิภาพเท่า WebSocket และด้วยเหตุผลเดียวกันนี้ BOSH อาจปรับขนาดได้ไม่ดีนัก) (Jingle เป็นส่วนขยาย XMPP ที่ใช้เปิดใช้เสียงและวิดีโอ โปรเจ็กต์ WebRTC ใช้คอมโพเนนต์เครือข่ายและการรับส่งจากไลบรารี libjingle ซึ่งเป็นการใช้งาน Jingle ใน C++

  • ไลบรารีโอเพนซอร์ส เช่น ZeroMQ (ตามที่ TokBox ใช้สำหรับบริการ Rumour) และ OpenMQ (NullMQ ใช้แนวคิด ZeroMQ กับแพลตฟอร์มเว็บโดยใช้โปรโตคอล STOMP ผ่าน WebSocket)

  • แพลตฟอร์มการรับส่งข้อความผ่านระบบคลาวด์เชิงพาณิชย์ที่ใช้ WebSocket (แม้ว่าอาจกลับไปใช้การสำรวจแบบยาว) เช่น Pusher, Kaazing และ PubNub (PubNub ยังมี API สำหรับ WebRTC ด้วย)

  • แพลตฟอร์ม WebRTC เชิงพาณิชย์ เช่น vLine

(Real-Time Web Technologies Guide ของนักพัฒนาซอฟต์แวร์ Phil Leggetter มีรายการบริการและไลบรารีการรับส่งข้อความที่ครอบคลุม)

สร้างบริการส่งสัญญาณด้วย Socket.io ใน Node

ต่อไปนี้คือโค้ดสำหรับเว็บแอปอย่างง่ายที่ใช้บริการส่งสัญญาณซึ่งสร้างด้วย Socket.io ใน Node การออกแบบของ Socket.io ทำให้การสร้างบริการเพื่อแลกเปลี่ยนข้อความเป็นเรื่องง่าย และ Socket.io เหมาะอย่างยิ่งสำหรับการส่งสัญญาณ WebRTC เนื่องจากมีแนวคิดเรื่องห้องในตัว ตัวอย่างนี้ไม่ได้ออกแบบมาเพื่อปรับขนาดเป็นบริการส่งสัญญาณระดับการผลิต แต่เข้าใจได้ง่ายสำหรับผู้ใช้จำนวนไม่มากนัก

Socket.io ใช้ WebSocket กับการสำรองข้อมูล ได้แก่ การสำรวจ AJAX แบบยาว, การสตรีม AJAX แบบหลายส่วน, Iframe แบบถาวร และการสำรวจ JSONP โดยมีการพอร์ตไปยังแบ็กเอนด์ต่างๆ แต่เวอร์ชัน Node ที่ใช้ในตัวอย่างนี้อาจเป็นเวอร์ชันที่รู้จักกันดีที่สุด

ตัวอย่างนี้ไม่มี WebRTC โดยออกแบบมาเพื่อแสดงวิธีสร้างการส่งสัญญาณในเว็บแอปเท่านั้น ดูบันทึกคอนโซลเพื่อดูสิ่งที่เกิดขึ้นเมื่อไคลเอ็นต์เข้าร่วมห้องและแลกเปลี่ยนข้อความ Codelab สำหรับ WebRTC นี้จะให้คำแนะนำแบบทีละขั้นตอนเกี่ยวกับวิธีผสานรวมฟีเจอร์นี้เข้ากับแอปวิดีโอแชท WebRTC ที่สมบูรณ์

ไคลเอ็นต์มีลักษณะดังนี้index.html

<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC client</title>
  </head>
  <body>
    <script src='/socket.io/socket.io.js'></script>
    <script src='js/main.js'></script>
  </body>
</html>

ต่อไปนี้คือไฟล์ JavaScript main.js ที่อ้างอิงในไคลเอ็นต์

const isInitiator;

room = prompt('Enter room name:');

const socket = io.connect();

if (room !== '') {
  console.log('Joining room ' + room);
  socket.emit('create or join', room);
}

socket.on('full', (room) => {
  console.log('Room ' + room + ' is full');
});

socket.on('empty', (room) => {
  isInitiator = true;
  console.log('Room ' + room + ' is empty');
});

socket.on('join', (room) => {
  console.log('Making request to join room ' + room);
  console.log('You are the initiator!');
});

socket.on('log', (array) => {
  console.log.apply(console, array);
});

ต่อไปนี้คือแอปเซิร์ฟเวอร์ที่สมบูรณ์

const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
  file.serve(req, res);
}).listen(2013);

const io = require('socket.io').listen(app);

io.sockets.on('connection', (socket) => {

  // Convenience function to log server messages to the client
  function log(){
    const array = ['>>> Message from server: '];
    for (const i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
      socket.emit('log', array);
  }

  socket.on('message', (message) => {
    log('Got message:', message);
    // For a real app, would be room only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', (room) => {
    const numClients = io.sockets.clients(room).length;

    log('Room ' + room + ' has ' + numClients + ' client(s)');
    log('Request to create or join room ' + room);

    if (numClients === 0){
      socket.join(room);
      socket.emit('created', room);
    } else if (numClients === 1) {
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room);
    } else { // max two clients
      socket.emit('full', room);
    }
    socket.emit('emit(): client ' + socket.id +
      ' joined room ' + room);
    socket.broadcast.emit('broadcast(): client ' + socket.id +
      ' joined room ' + room);

  });

});

(คุณไม่จำเป็นต้องเรียนรู้เกี่ยวกับ node-static สำหรับเรื่องนี้ (ซึ่งในตัวอย่างนี้มีการใช้คำว่า "การเข้าชม")

หากต้องการเรียกใช้แอปนี้ใน localhost คุณต้องติดตั้ง Node, Socket.IO และ node-static คุณดาวน์โหลด Node ได้จาก Node.js (การติดตั้งทำได้ง่ายและรวดเร็ว) หากต้องการติดตั้ง Socket.IO และ node-static ให้เรียกใช้ Node Package Manager จากเทอร์มินัลในไดเรกทอรีแอป

npm install socket.io
npm install node-static

หากต้องการเริ่มเซิร์ฟเวอร์ ให้เรียกใช้คำสั่งต่อไปนี้จากเทอร์มินัลในไดเรกทอรีแอป

node server.js

เปิด localhost:2013 จากเบราว์เซอร์ เปิดแท็บหรือหน้าต่างใหม่ในเบราว์เซอร์ใดก็ได้ แล้วเปิด localhost:2013 อีกครั้ง หากต้องการดูว่าเกิดอะไรขึ้น ให้ตรวจสอบคอนโซล ใน Chrome และ Opera คุณสามารถเข้าถึงคอนโซลผ่านเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของ Google Chrome ได้โดยใช้ Ctrl+Shift+J (หรือ Command+Option+J ใน Mac)

ไม่ว่าคุณจะเลือกใช้วิธีใดในการส่งสัญญาณ แบ็กเอนด์และแอปไคลเอ็นต์ของคุณจะต้องให้บริการที่คล้ายกับตัวอย่างนี้เป็นอย่างน้อย

ข้อควรระวังเกี่ยวกับการส่งสัญญาณ

  • RTCPeerConnection จะไม่เริ่มรวบรวมผู้สมัครจนกว่าจะมีการเรียกใช้ setLocalDescription() ซึ่งเป็นข้อกำหนดในฉบับร่าง JSEP ของ IETF
  • ใช้ประโยชน์จาก Trickle ICE โทรหา addIceCandidate() ทันทีที่ผู้สมัครมาถึง

เซิร์ฟเวอร์รับส่งสัญญาณสำเร็จรูป

หากไม่ต้องการสร้างเอง คุณสามารถใช้เซิร์ฟเวอร์การส่งสัญญาณ WebRTC ที่มีอยู่หลายตัว ซึ่งใช้ Socket.IO เหมือนกับตัวอย่างก่อนหน้าและผสานรวมกับไลบรารี JavaScript ของไคลเอ็นต์ WebRTC

  • webRTC.io เป็นหนึ่งในไลบรารีการแยกข้อมูลแรกๆ สำหรับ WebRTC
  • Signalmaster คือเซิร์ฟเวอร์การส่งสัญญาณที่สร้างขึ้นเพื่อใช้กับไลบรารีไคลเอ็นต์ JavaScript ของ SimpleWebRTC

หากไม่ต้องการเขียนโค้ดเลย คุณสามารถใช้แพลตฟอร์ม WebRTC เชิงพาณิชย์ที่สมบูรณ์จากบริษัทต่างๆ เช่น vLine, OpenTok และ Asterisk

Ericsson สร้างเซิร์ฟเวอร์การส่งสัญญาณโดยใช้ PHP บน Apache ในช่วงแรกๆ ของ WebRTC แม้ว่าตอนนี้จะล้าสมัยไปบ้างแล้ว แต่ก็ควรดูโค้ดหากคุณกำลังพิจารณาใช้สิ่งที่คล้ายกัน

ความปลอดภัยในการส่งสัญญาณ

"ความปลอดภัยคือศิลปะของการทำให้ไม่มีอะไรเกิดขึ้น"

Salman Rushdie

การเข้ารหัสเป็นข้อกำหนดสำหรับคอมโพเนนต์ WebRTC ทั้งหมด

อย่างไรก็ตาม มาตรฐาน WebRTC ไม่ได้กำหนดกลไกการส่งสัญญาณ ดังนั้นคุณจึงต้องทำให้การส่งสัญญาณปลอดภัย หากผู้โจมตีสามารถลักลอบใช้การส่งสัญญาณได้ ก็จะหยุดเซสชัน เปลี่ยนเส้นทางการเชื่อมต่อ และบันทึก ดัดแปลง หรือแทรกเนื้อหาได้

ปัจจัยที่สำคัญที่สุดในการรักษาความปลอดภัยของการส่งสัญญาณคือการใช้โปรโตคอลที่ปลอดภัย เช่น HTTPS และ WSS (เช่น TLS) ซึ่งจะช่วยให้มั่นใจได้ว่าจะไม่มีการดักจับข้อความที่ไม่ได้เข้ารหัส นอกจากนี้ โปรดระมัดระวังไม่ให้มีการออกอากาศข้อความการส่งสัญญาณในลักษณะที่ผู้โทรรายอื่นสามารถเข้าถึงได้โดยใช้เซิร์ฟเวอร์การส่งสัญญาณเดียวกัน

หลังจากส่งสัญญาณ: ใช้ ICE เพื่อรับมือกับ NAT และไฟร์วอลล์

สำหรับการส่งสัญญาณข้อมูลเมตา แอป WebRTC จะใช้เซิร์ฟเวอร์ตัวกลาง แต่สำหรับการสตรีมสื่อและข้อมูลจริงเมื่อสร้างเซสชันแล้ว RTCPeerConnection จะพยายามเชื่อมต่อไคลเอ็นต์โดยตรงหรือแบบเพียร์ทูเพียร์

ในโลกที่เรียบง่ายกว่านี้ อุปกรณ์ปลายทาง WebRTC ทุกเครื่องจะมีที่อยู่ที่ไม่ซ้ำกันซึ่งสามารถแลกเปลี่ยนกับอุปกรณ์อื่นๆ เพื่อสื่อสารกันโดยตรงได้

การเชื่อมต่อแบบเพียร์ทูเพียร์ที่เรียบง่าย
โลกที่ไม่มี NAT และไฟร์วอลล์

ในความเป็นจริงแล้ว อุปกรณ์ส่วนใหญ่อยู่หลังเลเยอร์ NAT อย่างน้อย 1 เลเยอร์ บางอุปกรณ์มีซอฟต์แวร์ป้องกันไวรัสที่บล็อกพอร์ตและโปรโตคอลบางอย่าง และหลายอุปกรณ์อยู่หลังพร็อกซีและไฟร์วอลล์ขององค์กร ไฟร์วอลล์และ NAT อาจได้รับการติดตั้งใช้งานโดยอุปกรณ์เดียวกัน เช่น เราเตอร์ Wi-Fi ในบ้าน

เพียร์ที่อยู่หลัง NAT และไฟร์วอลล์
โลกแห่งความเป็นจริง

แอป WebRTC สามารถใช้เฟรมเวิร์ก ICE เพื่อจัดการกับความซับซ้อนของการเชื่อมต่อเครือข่ายในโลกแห่งความเป็นจริง หากต้องการให้แอปทำเช่นนี้ได้ แอปต้องส่ง URL ของเซิร์ฟเวอร์ ICE ไปยัง RTCPeerConnection ตามที่อธิบายไว้ในบทความนี้

ICE พยายามค้นหาเส้นทางที่ดีที่สุดในการเชื่อมต่อเพียร์ โดยจะลองใช้ทุกความเป็นไปได้แบบคู่ขนานและเลือกตัวเลือกที่มีประสิทธิภาพที่สุดซึ่งใช้งานได้ ICE จะพยายามสร้างการเชื่อมต่อโดยใช้ที่อยู่โฮสต์ที่ได้จากระบบปฏิบัติการและการ์ดเครือข่ายของอุปกรณ์ก่อน หากไม่สำเร็จ (ซึ่งจะเกิดขึ้นกับอุปกรณ์ที่อยู่หลัง NAT) ICE จะรับที่อยู่ภายนอกโดยใช้เซิร์ฟเวอร์ STUN และหากไม่สำเร็จ ระบบจะกำหนดเส้นทางการรับส่งข้อมูลผ่านเซิร์ฟเวอร์รีเลย์ TURN

กล่าวคือ ระบบจะใช้เซิร์ฟเวอร์ STUN เพื่อรับที่อยู่เครือข่ายภายนอก และใช้เซิร์ฟเวอร์ TURN เพื่อส่งต่อการรับส่งข้อมูลหากการเชื่อมต่อโดยตรง (แบบเพียร์ทูเพียร์) ไม่สำเร็จ

เซิร์ฟเวอร์ TURN ทุกเครื่องรองรับ STUN เซิร์ฟเวอร์ TURN คือเซิร์ฟเวอร์ STUN ที่มีฟังก์ชันการทำงานของการรีเลย์ในตัวเพิ่มเติม นอกจากนี้ ICE ยังรับมือกับความซับซ้อนของการตั้งค่า NAT ได้ด้วย ในความเป็นจริง การเจาะรู NAT อาจต้องใช้มากกว่าแค่ที่อยู่ IP สาธารณะ:พอร์ต

แอป WebRTC จะระบุ URL สำหรับเซิร์ฟเวอร์ STUN และ/หรือ TURN (ไม่บังคับ) ในออบเจ็กต์การกำหนดค่า iceServers ซึ่งเป็นอาร์กิวเมนต์แรกของตัวสร้าง RTCPeerConnection สำหรับ appr.tc ค่าดังกล่าวจะมีลักษณะดังนี้

{
  'iceServers': [
    {
      'urls': 'stun:stun.l.google.com:19302'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

เมื่อ RTCPeerConnection มีข้อมูลดังกล่าวแล้ว ระบบจะดำเนินการตามกระบวนการ ICE โดยอัตโนมัติ RTCPeerConnection ใช้เฟรมเวิร์ก ICE เพื่อหาเส้นทางที่ดีที่สุดระหว่างเพียร์ โดยทำงานร่วมกับเซิร์ฟเวอร์ STUN และ TURN ตามความจำเป็น

STUN

NAT จะให้ที่อยู่ IP แก่อุปกรณ์เพื่อใช้ภายในเครือข่ายภายในส่วนตัว แต่จะใช้ที่อยู่นี้ภายนอกไม่ได้ หากไม่มีที่อยู่สาธารณะ พีียร์ WebRTC จะสื่อสารกันไม่ได้ WebRTC ใช้ STUN เพื่อหลีกเลี่ยงปัญหานี้

เซิร์ฟเวอร์ STUN อยู่บนอินเทอร์เน็ตสาธารณะและมีหน้าที่เดียวคือตรวจสอบที่อยู่ IP:พอร์ตของคำขอขาเข้า (จากแอปที่ทำงานอยู่เบื้องหลัง NAT) และส่งที่อยู่นั้นกลับไปเป็นการตอบกลับ กล่าวคือ แอปใช้เซิร์ฟเวอร์ STUN เพื่อค้นหา IP:port จากมุมมองสาธารณะ กระบวนการนี้ช่วยให้เพียร์ WebRTC ได้รับที่อยู่ที่เข้าถึงได้แบบสาธารณะสำหรับตัวเอง แล้วส่งที่อยู่นั้นไปยังเพียร์อื่นผ่านกลไกการส่งสัญญาณเพื่อตั้งค่าลิงก์โดยตรง (ในทางปฏิบัติ NAT แต่ละรายการจะทำงานแตกต่างกันและอาจมีเลเยอร์ NAT หลายรายการ แต่หลักการยังคงเหมือนเดิม)

เซิร์ฟเวอร์ STUN ไม่จำเป็นต้องทำอะไรมากหรือจดจำอะไรมาก ดังนั้นเซิร์ฟเวอร์ STUN ที่มีสเปคค่อนข้างต่ำจึงสามารถจัดการคำขอจำนวนมากได้

การโทรผ่าน WebRTC ส่วนใหญ่เชื่อมต่อได้สำเร็จโดยใช้ STUN ซึ่งอยู่ที่ 86% ตามข้อมูลจาก Webrtcstats.com แม้ว่าการโทรระหว่างเพียร์ที่อยู่เบื้องหลังไฟร์วอลล์และการกำหนดค่า NAT ที่ซับซ้อนอาจมีอัตราการเชื่อมต่อที่ต่ำกว่านี้

การเชื่อมต่อแบบเพียร์ทูเพียร์โดยใช้เซิร์ฟเวอร์ STUN
การใช้เซิร์ฟเวอร์ STUN เพื่อรับที่อยู่ IP สาธารณะ:พอร์ต

TURN

RTCPeerConnection พยายามตั้งค่าการสื่อสารโดยตรงระหว่างเพียร์ผ่าน UDP หากไม่สำเร็จ RTCPeerConnection จะใช้ TCP หากไม่สำเร็จ คุณสามารถใช้เซิร์ฟเวอร์ TURN เป็นตัวสำรองเพื่อส่งต่อข้อมูลระหว่างอุปกรณ์ปลายทาง

ขอย้ำอีกครั้งว่า TURN ใช้เพื่อส่งต่อสตรีมมิงเสียง วิดีโอ และข้อมูลระหว่างเพียร์ ไม่ใช่ข้อมูลการส่งสัญญาณ

เซิร์ฟเวอร์ TURN มีที่อยู่สาธารณะ ดังนั้นจึงสามารถติดต่อโดยเพียร์ได้แม้ว่าเพียร์จะอยู่หลังไฟร์วอลล์หรือพร็อกซีก็ตาม เซิร์ฟเวอร์ TURN มีหน้าที่ที่เรียบง่ายในเชิงแนวคิด นั่นคือการส่งต่อสตรีม อย่างไรก็ตาม เซิร์ฟเวอร์ TURN จะใช้แบนด์วิดท์จำนวนมากโดยธรรมชาติ ซึ่งแตกต่างจากเซิร์ฟเวอร์ STUN กล่าวคือ เซิร์ฟเวอร์ TURN ต้องมีประสิทธิภาพมากขึ้น

การเชื่อมต่อแบบเพียร์ทูเพียร์โดยใช้เซิร์ฟเวอร์ STUN
The full Monty: STUN, TURN, and signaling

แผนภาพนี้แสดงการทำงานของ TURN STUN อย่างเดียวไม่สำเร็จ ดังนั้นเพียร์แต่ละรายจึงหันไปใช้เซิร์ฟเวอร์ TURN

การติดตั้งใช้งานเซิร์ฟเวอร์ STUN และ TURN

สำหรับการทดสอบ Google จะเรียกใช้เซิร์ฟเวอร์ STUN สาธารณะ stun.l.google.com:19302 ตามที่ appr.tc ใช้ สำหรับบริการ STUN/TURN เวอร์ชันที่ใช้งานจริง ให้ใช้ rfc5766-turn-server ซอร์สโค้ดสำหรับเซิร์ฟเวอร์ STUN และ TURN พร้อมให้บริการบน GitHub ซึ่งคุณจะเห็นลิงก์ไปยังแหล่งข้อมูลหลายแห่งเกี่ยวกับการติดตั้งเซิร์ฟเวอร์ด้วย นอกจากนี้ยังมีอิมเมจ VM สำหรับ Amazon Web Services ด้วย

เซิร์ฟเวอร์ TURN ทางเลือกคือ restund ซึ่งมีให้ใช้งานเป็นซอร์สโค้ดและสำหรับ AWS วิธีการตั้งค่า restund ใน Compute Engine มีดังนี้

  1. เปิดไฟร์วอลล์ตามที่จำเป็นสำหรับ tcp=443, udp/tcp=3478
  2. สร้างอินสแตนซ์ 4 รายการ โดยแต่ละรายการจะมี IP สาธารณะ 1 รายการและอิมเมจ Ubuntu 12.06 มาตรฐาน
  3. ตั้งค่าไฟร์วอลล์ในเครื่อง (อนุญาตทั้งหมดจากทั้งหมด)
  4. ติดตั้งเครื่องมือโดยทำดังนี้ shell sudo apt-get install make sudo apt-get install gcc
  5. ติดตั้ง libre จาก creytiv.com/re.html
  6. ดึงข้อมูล restund จาก creytiv.com/restund.html และแตกไฟล์
  7. wget hancke.name/restund-auth.patch แล้วใช้กับ patch -p1 < restund-auth.patch
  8. เรียกใช้ make, sudo make install สำหรับ libre และ restund
  9. ปรับ restund.conf ให้ตรงกับความต้องการของคุณ (แทนที่ที่อยู่ IP และตรวจสอบว่ามีรหัสลับที่แชร์เดียวกัน) แล้วคัดลอกไปยัง /etc
  10. คัดลอก restund/etc/restund ไปยัง /etc/init.d/
  11. กำหนดค่าการคืนเงิน
    1. ตั้งค่า LD_LIBRARY_PATH
    2. คัดลอก restund.conf ไปยัง /etc/restund.conf
    3. ตั้งค่า restund.conf ให้ใช้ 10 ที่ถูกต้อง ที่อยู่ IP
  12. เรียกใช้ restund
  13. ทดสอบโดยใช้ไคลเอ็นต์ stund จากเครื่องระยะไกล: ./client IP:port

WebRTC แบบหลายฝ่าย

นอกจากนี้ คุณอาจต้องดูมาตรฐาน IETF ที่ Justin Uberti เสนอสำหรับ REST API สำหรับการเข้าถึงบริการ TURN

คุณนึกภาพ Use Case สำหรับการสตรีมสื่อที่นอกเหนือจากการโทรแบบหนึ่งต่อหนึ่งได้ง่ายๆ เช่น การประชุมทางวิดีโอระหว่างกลุ่มเพื่อนร่วมงานหรืองานสาธารณะที่มีผู้พูด 1 คนและผู้ชมหลายร้อยหรือหลายล้านคน

แอป WebRTC สามารถใช้ RTCPeerConnection หลายรายการเพื่อให้ทุกอุปกรณ์ปลายทางเชื่อมต่อกับอุปกรณ์ปลายทางอื่นๆ ทั้งหมดในการกำหนดค่าแบบเมช แอปอย่าง talky.io ใช้แนวทางนี้และใช้งานได้ดีอย่างน่าทึ่งสำหรับกลุ่มเพื่อนขนาดเล็ก นอกจากนี้ การประมวลผลและการใช้แบนด์วิดท์จะมากเกินไป โดยเฉพาะอย่างยิ่งสำหรับไคลเอ็นต์บนอุปกรณ์เคลื่อนที่

Mesh: การโทรแบบ N ทางขนาดเล็ก
โทโพโลยีแบบ Full Mesh: ทุกคนเชื่อมต่อกับทุกคน

หรือแอป WebRTC อาจเลือกปลายทางหนึ่งเพื่อกระจายสตรีมไปยังปลายทางอื่นๆ ทั้งหมดในการกำหนดค่าแบบดาว นอกจากนี้ คุณยังเรียกใช้ปลายทาง WebRTC บนเซิร์ฟเวอร์และสร้างกลไกการแจกจ่ายซ้ำของคุณเองได้ด้วย (webrtc.org มีแอปไคลเอ็นต์ตัวอย่างให้)

ตั้งแต่ Chrome 31 และ Opera 18 คุณสามารถใช้ MediaStream จาก RTCPeerConnection หนึ่งเป็นอินพุตสำหรับอีก RTCPeerConnection หนึ่งได้ ซึ่งจะช่วยให้สถาปัตยกรรมมีความยืดหยุ่นมากขึ้น เนื่องจากช่วยให้เว็บแอปจัดการการกำหนดเส้นทางการโทรได้โดยการเลือกเพียร์อื่นๆ ที่จะเชื่อมต่อ หากต้องการดูการทำงานของฟีเจอร์นี้ โปรดดูตัวอย่าง WebRTC การรีเลย์การเชื่อมต่อเพียร์และตัวอย่าง WebRTC การเชื่อมต่อเพียร์หลายรายการ

หน่วยควบคุมการประชุมทางวิดีโอ

ตัวเลือกที่ดีกว่าสำหรับอุปกรณ์ปลายทางจำนวนมากคือการใช้หน่วยควบคุมแบบหลายจุด (MCU) ซึ่งเป็นเซิร์ฟเวอร์ที่ทำหน้าที่เป็นบริดจ์เพื่อกระจายสื่อระหว่างผู้เข้าร่วมจำนวนมาก MCU สามารถรองรับความละเอียด ตัวแปลงรหัส และอัตราเฟรมที่แตกต่างกันในการประชุมทางวิดีโอ จัดการการแปลงรหัส ส่งต่อสตรีมแบบเลือก และมิกซ์หรือบันทึกเสียงและวิดีโอ สำหรับการโทรแบบหลายฝ่าย มีปัญหาหลายอย่างที่ต้องพิจารณา โดยเฉพาะวิธีแสดงอินพุตวิดีโอหลายรายการและมิกซ์เสียงจากหลายแหล่งที่มา แพลตฟอร์มระบบคลาวด์ เช่น vLine ก็พยายามเพิ่มประสิทธิภาพการกำหนดเส้นทางการรับส่งข้อมูลด้วย

คุณจะซื้อแพ็กเกจฮาร์ดแวร์ MCU แบบสมบูรณ์หรือจะสร้างขึ้นเองก็ได้

มุมมองด้านหลังของ Cisco MCU5300
ด้านหลังของ Cisco MCU

มีตัวเลือกซอฟต์แวร์ MCU แบบโอเพนซอร์สหลายตัว เช่น Licode (เดิมชื่อ Lynckia) ผลิต MCU แบบโอเพนซอร์สสำหรับ WebRTC OpenTok มี Mantis

นอกเหนือจากเบราว์เซอร์: VoIP, โทรศัพท์ และการรับส่งข้อความ

ลักษณะที่เป็นมาตรฐานของ WebRTC ช่วยให้สามารถสร้างการสื่อสารระหว่างแอป WebRTC ที่ทำงานในเบราว์เซอร์กับอุปกรณ์หรือแพลตฟอร์มที่ทำงานบนแพลตฟอร์มการสื่อสารอื่น เช่น โทรศัพท์หรือระบบการประชุมทางวิดีโอ

SIP เป็นโปรโตคอลการส่งสัญญาณที่ใช้โดยระบบ VoIP และการประชุมทางวิดีโอ หากต้องการเปิดใช้การสื่อสารระหว่างเว็บแอป WebRTC กับไคลเอ็นต์ SIP เช่น ระบบการประชุมทางวิดีโอ WebRTC จะต้องมีพร็อกซีเซิร์ฟเวอร์เพื่อเป็นตัวกลางในการส่งสัญญาณ การส่งสัญญาณต้องผ่านเกตเวย์ แต่เมื่อสร้างการสื่อสารแล้ว ทราฟิก SRTP (วิดีโอและเสียง) จะไหลผ่านแบบเพียร์ทูเพียร์ได้โดยตรง

เครือข่ายโทรศัพท์พื้นฐาน (PSTN) คือเครือข่ายการสลับวงจรของโทรศัพท์อนาล็อก "ธรรมดา" ทั้งหมด สำหรับการโทรระหว่างเว็บแอป WebRTC กับโทรศัพท์ การรับส่งข้อมูลต้องผ่านเกตเวย์ PSTN ในทำนองเดียวกัน เว็บแอป WebRTC ก็ต้องมีเซิร์ฟเวอร์ XMPP ตัวกลางเพื่อสื่อสารกับอุปกรณ์ปลายทาง Jingle เช่น ไคลเอ็นต์ IM Google พัฒนา Jingle เป็นส่วนขยายของ XMPP เพื่อเปิดใช้เสียงและวิดีโอสำหรับบริการรับส่งข้อความ การใช้งาน WebRTC ในปัจจุบันอิงตามไลบรารี libjingle ใน C++ ซึ่งเป็นการใช้งาน Jingle ที่พัฒนาขึ้นครั้งแรกสำหรับ Talk

แอป ไลบรารี และแพลตฟอร์มจำนวนมากใช้ความสามารถของ WebRTC ในการสื่อสารกับโลกภายนอก ดังนี้

  • sipML5: ไคลเอ็นต์ SIP ของ JavaScript แบบโอเพนซอร์ส
  • jsSIP: ไลบรารี SIP ของ JavaScript
  • Phono: JavaScript Phone API แบบโอเพนซอร์สที่สร้างขึ้นเป็นปลั๊กอิน
  • Zingaya: วิดเจ็ตโทรศัพท์ที่ฝังได้
  • Twilio: เสียงและการรับส่งข้อความ
  • Uberconference: การประชุม

นอกจากนี้ นักพัฒนา sipML5 ยังได้สร้างเกตเวย์ webrtc2sip ด้วย Tethr และ Tropo ได้สาธิตเฟรมเวิร์กสำหรับการสื่อสารในกรณีเกิดภัยพิบัติ "ในกระเป๋าเอกสาร" โดยใช้เซลล์ OpenBTS เพื่อเปิดใช้การสื่อสารระหว่างฟีเจอร์โฟนและคอมพิวเตอร์ผ่าน WebRTC ซึ่งเป็นการสื่อสารทางโทรศัพท์โดยไม่ต้องใช้ผู้ให้บริการ

ดูข้อมูลเพิ่มเติม

Codelab ของ WebRTC จะให้วิธีการแบบทีละขั้นตอนในการสร้างแอปแชทวิดีโอและแชทข้อความโดยใช้บริการส่งสัญญาณ Socket.io ที่ทำงานใน Node

การนำเสนอ WebRTC ใน Google I/O ปี 2013 โดย Justin Uberti หัวหน้าฝ่ายเทคโนโลยี WebRTC

การนำเสนอของ Chris Wilson ใน SFHTML5 - Introduction to WebRTC Apps

หนังสือ 350 หน้า WebRTC: APIs and RTCWEB Protocols of the HTML5 Real-Time Web มีรายละเอียดมากมายเกี่ยวกับเส้นทางข้อมูลและการส่งสัญญาณ รวมถึงมีแผนภาพโทโพโลยีเครือข่ายโดยละเอียดหลายรายการ

WebRTC และการส่งสัญญาณ: สิ่งที่ 2 ปีสอนเรา - บล็อกโพสต์ของ TokBox เกี่ยวกับเหตุผลที่การไม่รวมการส่งสัญญาณไว้ในข้อกำหนดเป็นความคิดที่ดี

คำแนะนำเชิงปฏิบัติในการสร้างแอป WebRTC ของ Ben Strong มีข้อมูลมากมายเกี่ยวกับโทโพโลยีและโครงสร้างพื้นฐานของ WebRTC

บท WebRTC ในIlya Grigorik High Performance Browser Networking เจาะลึกสถาปัตยกรรม กรณีการใช้งาน และประสิทธิภาพของ WebRTC