תחילת השימוש ב-WebRTC

WebRTC הוא חזית חדשה במלחמה הארוכה עבור אינטרנט פתוח ונטול הגבלות.

ברנדן אייך, ממציא JavaScript

דמיינו עולם שבו הטלפון, הטלוויזיה והמחשב יכולים לתקשר בפלטפורמה משותפת. נניח שהיה לך קל להוסיף לאפליקציית האינטרנט וידאו צ'אט ושיתוף נתונים מקצה לקצה. זה החזון של WebRTC.

רוצה לנסות? WebRTC זמין במחשבים ובניידים בדפדפנים Google Chrome, Safari, Firefox ו-Opera. מקום טוב להתחיל בו הוא אפליקציית וידאו צ'אט פשוטה בכתובת appr.tc:

  1. פותחים את appr.tc בדפדפן.
  2. לוחצים על הצטרפות כדי להצטרף לחדר צ'אט ולאפשר לאפליקציה להשתמש במצלמת האינטרנט.
  3. פותחים את כתובת ה-URL שמוצגת בסוף הדף בכרטיסייה חדשה, או במחשב אחר.

התחלה מהירה

אין לכם זמן לקרוא את המאמר הזה או שאתם רוצים רק קוד?

לחלופין, תוכלו לדלג ישירות אל Codelab של WebRTC, מדריך מפורט שמסביר איך לפתח אפליקציית וידאו צ'אט מלאה, כולל שרת איתות פשוט.

היסטוריה קצרה מאוד של WebRTC

אחד האתגרים העיקריים האחרונים באינטרנט הוא לאפשר תקשורת אנושית באמצעות קול ווידאו: תקשורת בזמן אמת או RTC בקיצור. RTC צריך להיות טבעי באפליקציית אינטרנט בדיוק כמו שמזינים טקסט בקלט טקסט. בלי זה, תהיה לכם הגבלה על היכולת שלכם לחדש ולפתח דרכים חדשות ליצירת אינטראקציה.

בעבר, פלטפורמת RTC הייתה עסקית ומורכבת, ודורשת רישיון או וידאו יקרות של וידאו ואודיו באופן ביתי. היה לי קשה לשלב טכנולוגיית RTC עם תוכן, נתונים ושירותים קיימים, והיה קשה במיוחד באינטרנט.

וידאו צ'אט ב-Gmail הפך לפופולרי בשנת 2008, ובשנת 2011 Google השיקה את Hangouts, שהשתמש ב-Google Talk (וכמוה גם Gmail). Google רכשה את GIPS, חברה שפיתחה רכיבים רבים שנדרשים ל-RTC, כמו קודקים וטכניקות לביטול הד. Google משתמשת בקוד פתוח של הטכנולוגיות שפותחו על ידי GIPS ועבדה עם גופי תקנים רלוונטיים בכוח המשימה של הנדסת תוכנה באינטרנט (IETF) וב-World Wide Web Consortium (W3C) כדי להבטיח קונצנזוס בתחום. במאי 2011, חברת Ericsson בנתה את היישום הראשון של WebRTC.

WebRTC יישם סטנדרטים פתוחים לתקשורת בזמן אמת, וידאו, אודיו ונתונים ללא יישומי פלאגין. הצורך היה אמיתי:

  • שירותי אינטרנט רבים השתמשו ב-RTC אבל הזדקקו להורדות, לאפליקציות נייטיב או ליישומי פלאגין. האפליקציות האלה כללו את Skype, Facebook ו-Hangouts.
  • הורדה, התקנה ועדכון של יישומי פלאגין היא פעולה מורכבת, לעיתים קרובות ומעלה שגיאות ומעצבנות.
  • קשה לפרוס יישומי פלאגין, לנפות באגים, לפתור בעיות, לבדוק אותם ולתחזק אותם. הם עשויים לדרוש רישוי ושילוב עם טכנולוגיה מורכבת ויקרה. לעיתים קרובות קשה לשכנע אנשים להתקין יישומי פלאגין מלכתחילה.

העקרונות המנחים של פרויקט WebRTC הם שממשקי ה-API שלו צריכים להיות בקוד פתוח, בחינם, סטנדרטיים, מובנים בדפדפני אינטרנט ויעילים יותר מטכנולוגיות קיימות.

איפה אנחנו עכשיו?

WebRTC משמש באפליקציות שונות, כמו Google Meet. WebRTC שולב גם עם אפליקציות מקוריות של WebKitGTK+ ו-Qt.

WebRTC מיישם את שלושת ממשקי ה-API הבאים: - MediaStream (מוכר גם בשם getUserMedia) - RTCPeerConnection - RTCDataChannel

ממשקי ה-API מוגדרים בשני המפרטים הבאים:

כל שלושת ממשקי ה-API נתמכים בניידים ובמחשבים באמצעות Chrome , Safari , Firefox , Edge ו-Opera.

getUserMedia: להדגמות וקוד, אפשר לעיין בדוגמאות WebRTC או לנסות את הדוגמאות המדהימות של כריס ווילסון, שמשתמשות ב-getUserMedia כקלט לאודיו באינטרנט.

RTCPeerConnection: להדגמה פשוטה ולאפליקציית וידאו צ'אט שמתפקדת באופן מלא, ראו דוגמאות של WebRTC חיבור להשוואה בין אפליקציות ו-appr.tc, בהתאמה. האפליקציה הזו משתמשת ב-adapter.js, סביבת shim של JavaScript שמופעלת על ידי Google בעזרת קהילת WebRTC, כדי להשמיט הבדלים בדפדפן ושינויים במפרטים.

RTCDataChannel: כדי לראות את התכונה הזו בפעולה, צריך לעיין בדוגמאות WebRTC כדי לצפות באחת מההדגמות של ערוץ הנתונים.

הקוד של WebRTC מראה איך להשתמש בכל שלושת ממשקי ה-API כדי לבנות אפליקציה פשוטה לווידאו צ'אט ולשיתוף קבצים.

WebRTC הראשון שלך

לאפליקציות WebRTC צריך לעשות כמה דברים:

  • לקבל סטרימינג של אודיו, וידאו או נתונים אחרים.
  • מקבלים פרטי רשת, כמו כתובות IP ויציאות, ומחליפים אותם בלקוחות WebRTC אחרים (שנקראים עמיתים) כדי להפעיל חיבור, גם דרך NATs וחומות אש.
  • לתאם תקשורת איתות כדי לדווח על שגיאות ולהתחיל או לסגור סשנים.
  • העברת מידע על מדיה ויכולות לקוח, כמו רזולוציה וקודקים.
  • להעביר אודיו, וידאו או נתונים בסטרימינג.

כדי לקבל ולהעביר נתוני סטרימינג, WebRTC מיישם את ממשקי ה-API הבאים:

  • MediaStream מקבל גישה למקורות נתונים, כמו המצלמה והמיקרופון של המשתמש.
  • RTCPeerConnection מאפשר שיחות אודיו או וידאו עם מתקנים להצפנה ולניהול של רוחב הפס.
  • RTCDataChannel מאפשר תקשורת מקצה לקצה (P2P) על נתונים גנריים.

(בהמשך ניתן למצוא דיון מפורט על הרשת ועל היבטים הקשורים לסימון WebRTC.)

API של MediaStream (נקרא גם API getUserMedia)

API של MediaStream מייצג שידורי מדיה מסונכרנים. לדוגמה, בסטרימינג שנלקח מהמצלמה ומהמיקרופון, הטראקים של וידאו ואודיו מסונכרנים. (אין לבלבל בין MediaStreamTrack לבין הרכיב <track>, שהוא משהו שונה לחלוטין.)

נראה שהדרך הקלה ביותר להבין את ה-API של MediaStream היא לבחון אותו בשטח:

  1. בדפדפן, עוברים אל דוגמאות WebRTC getUserMedia.
  2. פותחים את המסוף.
  3. בודקים את המשתנה stream, שנמצא בהיקף גלובלי.

לכל MediaStream יש קלט, שעשוי להיות MediaStream שנוצר על ידי getUserMedia(), ופלט שיועבר לרכיב וידאו או לRTCPeerConnection.

ה-method getUserMedia() לוקחת פרמטר של אובייקט MediaStreamConstraints ומחזירה ערך של Promise שמפנה לאובייקט MediaStream.

לכל MediaStream יש label, כמו 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'. מערך של MediaStreamTrack מוחזר באמצעות ה-methods getAudioTracks() ו-getVideoTracks().

בדוגמה getUserMedia, stream.getAudioTracks() מחזירה מערך ריק (כי אין אודיו) ובהנחה שמצלמת אינטרנט תקינה מחוברת, stream.getVideoTracks() מחזירה מערך של MediaStreamTrack שמייצג את השידור ממצלמת האינטרנט. לכל MediaStreamTrack יש סוג ('video' או 'audio'), label (משהו כמו 'FaceTime HD Camera (Built-in)'), והוא מייצג ערוץ אחד או יותר של אודיו או וידאו. במקרה כזה יש רק טראק אחד של וידאו ואין בו אודיו, אבל קל לדמיין תרחישי שימוש שבהם יש עוד טראקים. למשל, אפליקציית צ'אט שמקבלת סטרימינג מהמצלמה הקדמית, מהמצלמה האחורית, מהמיקרופון ואפליקציה שמשתפות את המסך שלה.

אפשר לצרף MediaStream לרכיב וידאו על ידי הגדרת המאפיין srcObject. בעבר, כדי לעשות את זה, צריך להגדיר את המאפיין src לכתובת URL של אובייקט שנוצרה באמצעות URL.createObjectURL(), אבל השיטה הזו הוצאה משימוש.

אפשר גם להשתמש ב-getUserMedia כצומת קלט ל-Web Audio API:

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

אפליקציות ותוספים המבוססים על Chromium יכולים גם לשלב את getUserMedia. הוספת הרשאות audioCapture ו/או videoCapture למניפסט מאפשרת לבקש הרשאה ולהעניק אותה רק פעם אחת לאחר ההתקנה. לאחר מכן, המשתמש לא מתבקש הרשאת גישה למצלמה או למיקרופון.

צריך להעניק הרשאה רק פעם אחת עבור getUserMedia(). בפעם הראשונה, לחצן 'אישור' מוצג בסרגל המידע של הדפדפן. גישת HTTP של getUserMedia() הוצאה משימוש על ידי Chrome בסוף 2015 כי היא סווגה כתכונה מועילה.

יכול להיות שהכוונה היא להפעיל MediaStream לכל מקור נתונים של סטרימינג, ולא רק למצלמה או למיקרופון. כך יתאפשר סטרימינג מנתונים מאוחסנים או ממקורות נתונים שרירותיים, כמו חיישנים או מקורות קלט אחרים.

getUserMedia() מתעורר לחיים בשילוב עם ספריות וממשקי API אחרים של JavaScript:

  • Webcam Toy היא אפליקציית תא צילום שמשתמשת ב-WebGL כדי להוסיף אפקטים משונים ונפלאים לתמונות שאפשר לשתף או לשמור באופן מקומי.
  • FaceKat הוא משחק למעקב אחר זיהוי הפנים שנוצר באמצעות headtrackr.js.
  • מצלמת ASCII משתמשת ב-Canvas API כדי ליצור תמונות ASCII.
תמונת ASCII שנוצרה על ידי idevelop.ro/ascii-camera
גרפיקה מסוג gUM ASCII

מגבלות

אפשר להשתמש במגבלות כדי להגדיר ערכים לרזולוציית הסרטון getUserMedia(). כך מתאפשרת גם תמיכה במגבלות אחרות, כמו יחס גובה-רוחב. מצב פנייה (מצלמה קדמית או אחורית); קצב הפריימים, גובה ורוחב; ו-applyConstraints().

לדוגמה, ראו דוגמאות WebRTC getUserMedia: בחירת רזולוציה.

אם מגדירים ערך אילוץ אסור, הפונקציה נותנת DOMException או OverconstrainedError אם, למשל, לא התקבלה בקשה לפתרון הבעיה. כדי לראות את זה בפעולה, אפשר לעיין בדוגמאות WebRTC getUserMedia: צריך לבחור רזולוציה להדגמה.

צילום מסך וכרטיסיות

אפליקציות Chrome מאפשרות גם לשתף סרטון בזמן אמת בכרטיסייה אחת בדפדפן או את כל המחשב באמצעות ממשקי API של chrome.tabCapture ושל chrome.desktopCapture. (להדגמה ומידע נוסף, אפשר לעיין במאמר שיתוף מסך באמצעות WebRTC. המאמר הזה בן מספר שנים, אבל הוא עדיין מעניין.)

אפשר גם להשתמש בצילום המסך כמקור MediaStream ב-Chrome באמצעות האילוץ הניסיוני chromeMediaSource. שימו לב: צילום המסך מחייב HTTPS וכדאי להשתמש בו רק לצורכי פיתוח, כי הוא מופעל באמצעות סימון שורת הפקודה (CLI), כמו שמוסבר בפוסט הזה.

איתות: מידע על בקרת סשנים, רשת ומדיה

WebRTC משתמש ב-RTCPeerConnection כדי להעביר נתוני סטרימינג בין דפדפנים (שידועים גם כעמיתים), אבל הוא זקוק גם למנגנון לתיאום תקשורת ולשליחת הודעות בקרה, תהליך שנקרא איתות. שיטות ופרוטוקולים של איתות לא מצוינים ב-WebRTC. האיתות הוא לא חלק מ-API של RTCPeerConnection.

במקום זאת, המפתחים של אפליקציות WebRTC יכולים לבחור בכל פרוטוקול להעברת הודעות שהם מעדיפים, כמו SIP או XMPP, וכל ערוץ תקשורת דו-כיווני (דו-כיווני) מתאים. בדוגמה של appr.tc נעשה שימוש ב-XHR וב-Channel API כמנגנון האות. ב-codelab נעשה שימוש ב-Socket.io שפועל בשרת Node.

איתות משמש להעברה של שלושה סוגי מידע:

  • הודעות לבקרת סשנים: לאתחול או לסגירה של הודעות תקשורת ולדווח על שגיאות.
  • הגדרת רשת: לעולם החיצוני, מה כתובת ה-IP והיציאה של המחשב?
  • יכולות מדיה: באילו קודקים ורזולוציות יש הדפדפן והדפדפן שאיתו הוא רוצה לתקשר?

העברת המידע באמצעות אותות צריכה להסתיים בהצלחה לפני שניתן יהיה להתחיל סטרימינג מקצה לקצה.

לדוגמה, נניח שמיכל רוצה לתקשר עם יוסי. הנה דוגמת קוד ממפרט W3C WebRTC, שמראה את תהליך האותות בפעולה. הקוד מתבסס על ההנחה שקיים מנגנון איתות מסוים שנוצר בשיטה createSignalingChannel(). חשוב גם לשים לב שב-Chrome וב-Opera, התחילית של RTCPeerConnection היא בשלב הזה.

// 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);
  }
};

// Once 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);
  }
};

ראשית, אליס ויוסי מחליפים פרטי רשת. (הביטוי מציאת המועמדים מתייחס לתהליך של מציאת ממשקי רשת ויציאות באמצעות מסגרת ICE).

  1. ליאל יוצרת אובייקט RTCPeerConnection עם handler של onicecandidate, שרץ כשהמועמדים לרשתות הופכים לזמינים.
  2. אליס שולחת נתוני מועמדים סידוריים אל יוסי דרך ערוץ האיתות שבו היא משתמשת, כגון WebSocket או מנגנון אחר.
  3. כשיוסי מקבל הודעה ממועמד/ת, הוא מתקשר אל addIceCandidate כדי להוסיף את המועמד/ת לתיאור של האפליקציה המרוחקת.

לקוחות WebRTC (שנקראים גם עמיתים, או אליס ויוסי בדוגמה הזו) צריכים גם לבדוק ולהחליף נתוני מדיה אודיו ווידאו מקומיים ומרוחקים, כמו יכולות רזולוציה וקודק. איתות להחלפת מידע על הגדרות מדיה מתבצע על ידי העברת הצעה ותשובה באמצעות פרוטוקול תיאור הסשן (SDP):

  1. דפנה מפעילה את ה-method RTCPeerConnection createOffer(). ההחזרה מכאן מועברת על ידי RTCSessionDescription - תיאור הסשן המקומי של אליס.
  2. בקריאה החוזרת, ליאל מגדירה את התיאור המקומי באמצעות setLocalDescription() ואז שולחת את תיאור הסשן הזה ליוסי דרך ערוץ האיתות שלו. לתשומת ליבך, מערכת RTCPeerConnection תתחיל לאסוף מועמדים רק אחרי קריאה של setLocalDescription(). הנתונים האלה מקודדים בטיוטה של JSEP IETF.
  3. יוסי מגדיר את התיאור שאליס שלחה לו כתיאור מרחוק באמצעות setRemoteDescription().
  4. יוסי מפעיל את השיטה RTCPeerConnection createAnswer() ומעביר אליה את התיאור מרחוק שהוא קיבל מאלי כדי שניתן יהיה ליצור סשן מקומי שתואם לשלה. הקריאה החוזרת של createAnswer() עברה RTCSessionDescription. יוסי מגדיר זאת כתיאור המקומי ושולח אותו לאיס.
  5. כשאליס מקבלת את תיאור הסשן של יוסי, היא מגדירה אותו כתיאור מרחוק עם setRemoteDescription.
  6. פינג!

אובייקטים מסוג RTCSessionDescription הם פריטי blob שתואמים ל-Session Description Protocol (פרוטוקול תיאור הסשן) או SDP. אובייקט SDP נראה כך:

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

ניתן לבצע רכישה והחלפה של מידע על רשתות ועל מדיה בו-זמנית, אך על שני התהליכים להשלים לפני שמתחילים לשדר אודיו ווידאו בין עמיתים.

ארכיטקטורת ההצעה/תשובה שתוארה קודם לכן נקראת פרוטוקול JavaScript לשימוש בסשן, או JSEP. (יש אנימציה מצוינת שמסבירה את תהליך האיתות והסטרימינג בסרטון ההדגמה של אריקסון להטמעה הראשונה של WebRTC.)

תרשים ארכיטקטורה של JSEP
ארכיטקטורת JSEP

אחרי שתהליך האותות הסתיים בהצלחה, ניתן להעביר נתונים בסטרימינג ישירות מקצה לקצה, בין המתקשר למקבל הקריאה החוזרת – או, אם הפעולה נכשלת, דרך שרת ממסר מתווך (מידע נוסף על כך בהמשך). סטרימינג הוא המשימה של RTCPeerConnection.

RTCPeerConnection

RTCPeerConnection הוא רכיב ה-WebRTC שמטפל בתקשורת יציבה ויעילה של נתונים בסטרימינג בין אפליקציות להשוואה.

בתרשים הארכיטקטורה של WebRTC מוצג התפקיד של RTCPeerConnection. כפי שתוכלו לראות, החלקים הירוקים הם מורכבים!

תרשים ארכיטקטורה של WebRTC
ארכיטקטורת WebRTC (מ-webrtc.org)

מבחינת JavaScript, הדבר העיקרי שצריך להבין מהתרשים הזה הוא ש-RTCPeerConnection מגן על מפתחי האינטרנט מפני המורכבות האדירה שאורבים. הקודק והפרוטוקולים שבהם נעשה שימוש ב-WebRTC עושים מאמצים רבים כדי לאפשר תקשורת בזמן אמת, אפילו ברשתות לא אמינות:

  • הסתרה של אובדן מנות
  • ביטול הד
  • התאמה של רוחב הפס
  • אגירת נתונים דינמית של רעידות
  • השגת שליטה באופן אוטומטי
  • הפחתת רעש וביטול הרעש
  • ניקוי תמונות

קוד W3C הקודם מציג דוגמה פשוטה ל-WebRTC מנקודת מבט של אותות. בהמשך מוצגים הדרכה מפורטת על שתי אפליקציות WebRTC פעילות. הראשונה היא דוגמה פשוטה שממחישה את RTCPeerConnection והשנייה היא לקוח וידאו צ'אט פעיל באופן מלא.

RTCPeerConnection ללא שרתים

הקוד הבא נלקח מדוגמאות של WebRTC חיבור בין רשתות שכנות, עם RTCPeerConnection מקומי וגם מרוחק (וגם וידאו מקומי ומרוחק) בדף אינטרנט אחד. זה לא נותן שום דבר שימושי מאוד – המתקשר והמקבל הקריאה החוזרת נמצאים באותו דף, אבל זה מבהיר קצת את אופן הפעולה של ה-API של RTCPeerConnection, כי האובייקטים של RTCPeerConnection בדף יכולים לשלוח ולקבל נתונים והודעות ישירות בלי להשתמש במנגנוני איתות מתווכים.

בדוגמה הזו, pc1 מייצג את האפליקציה להשוואה (callee) מהסביבה הקרובה (callee), ו-pc2 מייצג את האפליקציה להשוואה מרחוק.

מתקשר

  1. יצירת RTCPeerConnection חדש והוספת השידור מה-getUserMedia(): ```js // Servers הוא קובץ תצורה אופציונלי. (עיינו בדיון של בהמשך ו-STUN בהמשך). pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) =&gt; { pc1.addTrack(track, LocalStream); });
  1. יוצרים מבצע ומגדירים אותו כתיאור מקומי של pc1 וכתיאור מרחוק של pc2. ניתן לעשות זאת ישירות בקוד בלי להשתמש באותות כי גם המתקשר וגם מקבל הקריאה החוזרת נמצאים באותו דף: js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

מקבל הקריאה החוזרת

  1. יוצרים pc2 וכשמוסיפים את השידור של pc1, אפשר להציג אותו ברכיב וידאו: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection API + שרתים

בעולם האמיתי, ל-WebRTC צריך להיות שרתים, אבל ברמה הזאת יכולים להיות:

  • משתמשים מגלים זה את זה ומחליפים פרטים מהעולם האמיתי, כמו שמות.
  • אפליקציות לקוח של WebRTC (עמיתים) מחליפות פרטי רשת.
  • אפליקציות להשוואה משתמשות בנתונים על מדיה, כמו פורמט הווידאו והרזולוציה.
  • אפליקציות לקוח WebRTC חוצות את שערי ה-NAT וחומות האש.

במילים אחרות, ל-WebRTC נדרשים ארבעה סוגים של פונקציונליות בצד השרת:

  • גילוי משתמשים ותקשורת
  • איתות
  • NAT/מעבר לחומת אש
  • שרתי ממסר במקרה של כשל בתקשורת עמית-לעמית

המאמר הזה לא כולל את מעברי NAT, רשתות מקצה לקצה (P2P) והדרישות לפיתוח אפליקציית שרת לגילוי ולאיתות של משתמשים. מספיק לציין שפרוטוקול STUN והתוסף שלו, TURN, משמשים את מסגרת ICE כדי לאפשר ל-RTCPeerConnection להתמודד עם מעבר NAT וטווחים אחרים ברשת.

ICE היא מסגרת ליצירת קשרים בין עמיתים, כמו שני לקוחות וידאו צ'אט. בהתחלה, ארגון ICE מנסה לחבר עמיתים ישירות עם זמן אחזור קצר ככל האפשר באמצעות UDP. בתהליך הזה, לשרתי STUN יש משימה אחת: לאפשר לעמית שמאחורי NAT לגלות את הכתובת הציבורית שלו ואת היציאה שלו. (מידע נוסף על STUN ועל השבתה זמין במאמר בניית השירותים לקצה העורפי שדרושים לאפליקציית WebRTC).

חיפוש מועמדים לחיבור
איך מוצאים מועמדים לחיבור

אם ה-UDP נכשל, מערכת ICE תנסה להשתמש ב-TCP. אם החיבור הישיר נכשל, במיוחד בגלל מעבר NAT וחומות אש בארגון, ICE משתמש בשרת סתום מתווך (ממסר). במילים אחרות, ארגון ICE משתמש קודם ב-STUN עם UDP כדי לחבר אפליקציות ישירות. אם הפעולה נכשלת, התוכנה עוברת לשרת ממסר הפעלה. הביטוי מציאת המועמדים מתייחס לתהליך של איתור ממשקי רשת ויציאות.

מסלולי נתונים של WebRTC
נתיבי נתונים מ-WebRTC

מהנדס WebRTC ג'סטין אוברטי מספק מידע נוסף על ICE, STUN ו-WebRTC במצגת של Google I/O WebRTC לשנת 2013. (השקפים במצגת נותנים דוגמאות להטמעות של שרת TURN ו-STUN).

לקוח פשוט של וידאו צ'אט

מקום טוב לנסות את WebRTC, כולל איתות ומעבר של NAT/חומת אש באמצעות שרת STUN, הוא סרטון ההדגמה של הווידאו צ'אט בכתובת appr.tc. האפליקציה הזו משתמשת ב-adapter.js – ספריית shim לבידוד אפליקציות מפני שינויי מפרטים והבדלים בקידומת.

הקוד מופיע באופן מכוון ביומן הרישום ביומן שלו. כדאי לבדוק במסוף כדי להבין את סדר האירועים. בהמשך מוצגת הדרכה מפורטת לגבי הקוד.

הטופולוגיות של הרשת

WebRTC, כפי שמיושם כרגע, תומך רק בתקשורת אחד על אחד, אבל ניתן להשתמש בו בתרחישי רשת מורכבים יותר, כמו למשל עם מספר עמיתים שמתקשרים ביניהם ישירות או באמצעות יחידה לבקרה מרובת נקודות (MCU), שרת שיכול לטפל במספר גדול של משתתפים ולבצע העברה סלקטיבית של סטרימינג, וגם מיקס או הקלטה של אודיו ווידאו.

תרשים הטופולוגיה של יחידת הבקרה מרובת נקודות
דוגמה לטופולוגיה של יחידת בקרה מרובת נקודות

הרבה אפליקציות WebRTC קיימות מדגימות רק תקשורת בין דפדפני אינטרנט, אבל שרתי שער יכולים לאפשר לאפליקציית WebRTC שפועלת בדפדפן ליצור אינטראקציה עם מכשירים, כמו טלפונים (שנקראים גם PSTN) ועם מערכות VOIP. במאי 2012, Doubango Telecom יצר את לקוח ה-SIP sipml5 שנוצר באמצעות WebRTC ו-WebSocket, וכך (בין שימושים פוטנציאליים אחרים) הוא מאפשר שיחות וידאו בין דפדפנים ואפליקציות שפועלים ב-iOS וב-Android. ב-Google I/O, טת' ו-Tropo הדגימו מסגרת לתקשורת בשעת אסון בתיק מסמכים באמצעות תא OpenBTS כדי לאפשר תקשורת בין טלפונים ניידים ומחשבים באמצעות WebRTC. תקשורת טלפונית ללא ספק!

הדגמה של Tethr/Tropo ב-Google I/O 2012
Tethr/Tropo: תקשורת בשעת אסון בתיק מסמכים

RTCDataChannel API<

נוסף על אודיו ווידאו, WebRTC תומך בתקשורת בזמן אמת בסוגי נתונים אחרים.

ה-API של RTCDataChannel מאפשר חילופי נתונים שרירותיים מקצה לקצה (P2P) עם זמן אחזור נמוך ותפוקה גבוהה. להדגמות בדף יחיד וכדי ללמוד איך לפתח אפליקציה פשוטה להעברת קבצים, כדאי לעיין בדוגמאות WebRTC וב-Codelab, בהתאמה.

יש הרבה תרחישים לדוגמה של שימוש ב-API, ביניהם:

  • משחקים
  • אפליקציות Remote Desktop
  • צ'אט טקסט בזמן אמת
  • העברת קבצים
  • רשתות מבוזרות

ה-API כולל כמה תכונות שיעזרו לכם להפיק את המקסימום מ-RTCPeerConnection ולאפשר תקשורת יעילה וגמישה בין עמיתים:

  • מינוף של הגדרת הסשן של RTCPeerConnection
  • מספר ערוצים בו-זמנית עם תעדוף
  • סמנטיקה של הצגת מודעות אמינה ולא אמינה
  • אבטחה מובנית (DTLS) ובקרת עומס
  • יכולת להשתמש עם או בלי אודיו או וידאו

התחביר דומה בכוונה ל-WebSocket עם שיטת send() ואירוע message:

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

התקשורת מתרחשת ישירות בין דפדפנים, ולכן RTCDataChannel יכול להיות מהיר הרבה יותר מ-WebSocket גם אם נדרש שרת ממסר (הפעלה) כשמתבצעת יצירת חורים כדי להתמודד עם חומות אש ו-NATs נכשלים.

RTCDataChannel זמין בדפדפני Chrome , Safari , Firefox , Opera ו-Samsung Internet. המשחק Cube Slam משתמש ב-API כדי להעביר את מצב המשחק. משחקים חבר או משחקים בדוב! הפלטפורמה החדשנית Sharefest שאפשרה שיתוף קבצים באמצעות RTCDataChannel ו-peerCDN נותנת הצצה לאופן שבו WebRTC יכול לאפשר הפצת תוכן מקצה לקצה.

למידע נוסף על RTCDataChannel אפשר לעיין במפרט פרוטוקול טיוטה של IETF.

אבטחה

יש כמה דרכים שבהן אפליקציה או פלאגין של תקשורת בזמן אמת עלולים לפגוע באבטחה. לדוגמה:

  • מדיה או נתונים לא מוצפנים עלולים ליירט בין דפדפנים, או בין דפדפן לשרת.
  • אפליקציה עשויה להקליט ולהפיץ וידאו או אודיו ללא ידיעת המשתמש.
  • יכול להיות שתוכנות זדוניות או וירוסים יותקנו לצד פלאגין או אפליקציה שאינם מזיקים לכאורה.

ל-WebRTC יש כמה תכונות כדי למנוע את הבעיות האלה:

  • יישומים של WebRTC משתמשים בפרוטוקולים מאובטחים כמו DTLS ו-SRTP.
  • חובה להצפין את כל רכיבי WebRTC, כולל מנגנוני אותות.
  • WebRTC הוא לא פלאגין. הרכיבים שלו פועלים בארגז החול של הדפדפן ולא בתהליך נפרד. הרכיבים לא דורשים התקנה נפרדת והם מתעדכנים בכל פעם שהדפדפן מתעדכן.
  • צריך להעניק גישה למצלמה ולמיקרופון באופן מפורש, וכשהמצלמה או המיקרופון פועלים, הגישה הזו מוצגת בבירור בממשק המשתמש.

דיון מלא בנושא אבטחה של מדיה בסטרימינג לא נכלל במאמר הזה. מידע נוסף זמין במאמר ארכיטקטורת האבטחה המוצעת של WebRTC שמוצעת על ידי ה-IETF.

לסיכום

ממשקי ה-API והסטנדרטים של WebRTC יכולים להעביר ולבזר כלים ליצירת תוכן ולהעברתם בצורה דמוקרטית, כולל שירותי טלפוניה, גיימינג, הפקת סרטונים, יצירת מוזיקה ואיסוף חדשות.

טכנולוגיה יותר משבשת בדרך הזו.

כמו שבלוגר פיל אדהולם אמר זאת, "יכול להיות ש-WebRTC ו-HTML5 יכולים לאפשר את אותה המרה לתקשורת בזמן אמת כמו הדפדפן המקורי לקבלת מידע".

כלים למפתחים

מידע נוסף

תקנים ופרוטוקולים

סיכום התמיכה של WebRTC

ממשקי API של MediaStream ו-getUserMedia

  • Chrome למחשב שולחני מגרסה 18.0.1008 ואילך; Chrome ל-Android מגרסה 29 ואילך
  • Opera בגרסה 18 ומעלה; Opera ל-Android 20 ואילך
  • Opera 12, Opera Mobile 12 (מבוסס על מנוע Presto)
  • Firefox מגרסה 17 ואילך
  • Microsoft Edge בגרסה 16 ואילך
  • Safari 11.2 ואילך ב-iOS ו-11.1 ואילך ב-MacOS
  • UC 11.8 ומעלה ב-Android
  • Samsung Internet 4 ואילך

API של RTCPeerConnection

  • Chrome למחשב מגרסה 20 ואילך; Chrome ל-Android מגרסה 29 ואילך (ללא סימון)
  • Opera בגרסה 18 ומעלה (מופעלת כברירת מחדל). Opera ל-Android 20 ואילך (מופעלת כברירת מחדל)
  • Firefox 22 ואילך (מופעל כברירת מחדל)
  • Microsoft Edge בגרסה 16 ואילך
  • Safari 11.2 ואילך ב-iOS ו-11.1 ואילך ב-MacOS
  • Samsung Internet 4 ואילך

API של RTCDataChannel

  • גרסה ניסיונית ב-Chrome 25, אבל יציבה יותר (עם יכולת פעולה הדדית של Firefox) ב-Chrome 26 ואילך; Chrome ל-Android מגרסה 29 ואילך
  • גרסה יציבה (עם יכולת פעולה הדדית של Firefox) ב-Opera 18 ואילך; Opera ל-Android 20 ואילך
  • Firefox 22 ואילך (מופעל כברירת מחדל)

למידע מפורט יותר על תמיכה בפלטפורמות שונות בממשקי API, כמו getUserMedia ו-RTCPeerConnection, אפשר לעיין ב-caniuse.com ובסטטוס פלטפורמת Chrome.

ממשקי API מקוריים של RTCPeerConnection זמינים גם במסמכי התיעוד באתר webrtc.org.