WebRTC הוא חזית חדשה במלחמה הארוכה למען אינטרנט פתוח וללא כבלים.
ברנדן אייך (Brendan Eich), ממציא JavaScript
תקשורת בזמן אמת ללא פלאגינים
דמיינו עולם שבו הטלפון, הטלוויזיה והמחשב שלכם יכולים לתקשר בפלטפורמה משותפת. נסו לדמיין כמה קל יהיה להוסיף לאפליקציית האינטרנט שלכם שיחות וידאו ושימוש בשיתוף נתונים מקצה לקצה. זוהי התפיסה של WebRTC.
רוצה לנסות? WebRTC זמין במחשבים ובניידים בדפדפנים Google Chrome, Safari, Firefox ו-Opera. מקום טוב להתחיל בו הוא אפליקציית הווידאו צ'אט הפשוטה בכתובת appr.tc:
- פותחים את appr.tc בדפדפן.
- לוחצים על הצטרפות כדי להצטרף לקבוצת צ'אט ולאפשר לאפליקציה להשתמש באינטרנט.
- פותחים את כתובת ה-URL שמוצגת בסוף הדף בכרטיסייה חדשה, או עדיף במחשב אחר.
התחלה מהירה
אין לכם זמן לקרוא את המאמר הזה או שאתם רוצים רק את הקוד?
- כדי לקבל סקירה כללית על WebRTC, אפשר לצפות בסרטון הבא מ-Google I/O או לעיין במצגות האלה:
- אם עדיין לא השתמשתם ב-API של
getUserMedia
, כדאי לעיין במאמרים צילום אודיו ווידאו ב-HTML5 וsimpl.info getUserMedia. - מידע נוסף על ה-API של
RTCPeerConnection
זמין בדוגמה הבאה ובמאמר 'simpl.info RTCPeerConnection'. - כדי ללמוד איך WebRTC משתמש בשרתים לסימון, ולחצירת חומות אש ו-NAT, אפשר לעיין בקוד וביומני המסוף ב-appr.tc.
- אין לכם זמן לחכות ואתם רוצים לנסות את WebRTC עכשיו? כדאי לנסות כמה מיותר מ-20 הדמואים שמפעילים את ממשקי ה-API של JavaScript ב-WebRTC.
- נתקלתם בבעיות במכונה וב-WebRTC? פותר הבעיות של WebRTC
לחלופין, אפשר לעבור ישירות אל codelab של WebRTC, מדריך מפורט שמסביר איך ליצור אפליקציית וידאו צ'אט מלאה, כולל שרת איתות פשוט.
היסטוריה קצרה מאוד של WebRTC
אחד מהאתגרים הגדולים האחרונים באינטרנט הוא לאפשר תקשורת בין בני אדם באמצעות קול ווידאו: תקשורת בזמן אמת, או RTC בקיצור. השימוש ב-RTC באפליקציית אינטרנט צריך להיות טבעי כמו הזנת טקסט בתיבת טקסט. בלי הנתונים האלה, היכולת שלכם לחדש ולפתח דרכים חדשות ליצירת אינטראקציה עם אנשים מוגבלת.
בעבר, RTC היה מורכב ועסקי, והיה צורך ברישיון לטכנולוגיות אודיו ווידאו יקרות או בפיתוח שלהן בתוך הארגון. שילוב של טכנולוגיית RTC עם תוכן, נתונים ושירותים קיימים היה קשה וגוזל זמן, במיוחד באינטרנט.
שיחות הווידאו ב-Gmail הפכו לפופולריות בשנת 2008, ובשנת 2011 Google השיקה את Hangouts, שמשתמש ב-Talk (כמו Gmail). Google רכשה את GIPS, חברה שפיתח רכיבים רבים שנדרשים ל-RTC, כמו קודיקים ושיטות לביטול הדהוד. Google פרסמה בקוד פתוח את הטכנולוגיות שפותחו על ידי GIPS, והתחברה לגופים הרלוונטיים לקביעת סטנדרטים ב-Internet Engineering Task Force (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 או לנסות את הדוגמאות המדהימות של Chris Wilson, שבהן getUserMedia
משמש כקלט של אודיו באינטרנט.
RTCPeerConnection
: כדי לראות הדגמה פשוטה ואפליקציית וידאו צ'אט פונקציונלית לגמרי, אפשר לעיין ב-WebRTC samples Peer connection וב-appr.tc, בהתאמה. האפליקציה הזו משתמשת ב-adapter.js, תוסף JavaScript שנמצא בטיפול Google בעזרת קהילת WebRTC, כדי להסתיר את ההבדלים בין הדפדפנים ואת השינויים במפרט.
RTCDataChannel
: כדי לראות את זה בפעולה, אפשר לעיין בדוגמאות ל-WebRTC ולבדוק את אחת מהדמו של נתוני הערוץ.
בcodelab של WebRTC מוסבר איך להשתמש בכל שלושת ממשקי ה-API כדי ליצור אפליקציה פשוטה לשיחות וידאו ולשיתוף קבצים.
השיחה הראשונה ב-WebRTC
אפליקציות WebRTC צריכות לבצע כמה פעולות:
- לקבל סטרימינג של אודיו, וידאו או נתונים אחרים.
- לקבל מידע על הרשת, כמו כתובות IP ויציאות, ולשתף אותו עם לקוחות WebRTC אחרים (שנקראים עמיתים) כדי לאפשר חיבור, גם דרך שרתי NAT וחומת אש.
- תיאום תקשורת איתותים לדיווח על שגיאות ולהפעלה או לסגירה של סשנים.
- החלפת מידע על המדיה ועל יכולות הלקוח, כמו רזולוציה וקודקים.
- העברת אודיו, וידאו או נתונים בסטרימינג.
כדי לקבל נתוני סטרימינג ולשלוח אותם, WebRTC מטמיע את ממשקי ה-API הבאים:
- ל-
MediaStream
יש גישה למקורות נתונים, כמו המצלמה והמיקרופון של המשתמש. RTCPeerConnection
מאפשרת שיחות אודיו או וידאו עם אפשרויות להצפנה ולניהול רוחב הפס.RTCDataChannel
מאפשר תקשורת בין משתמשים ללא צורך בשרת (P2P) של נתונים כלליים.
(בהמשך נדון בפירוט בהיבטים של הרשת והאיתות של WebRTC).
MediaStream
API (נקרא גם getUserMedia
API)
MediaStream
API מייצג סטרימינג מסונכרן של מדיה. לדוגמה, בשידור שנלקח מקלט המצלמה והמיקרופון יש טראקים מסונכרנים של וידאו ואודיו. (אין לבלבל בין MediaStreamTrack
לאלמנט <track>
, שהוא משהו שונה לגמרי).
הדרך הקלה ביותר להבין את ה-API של MediaStream
היא להסתכל עליו בפעולה:
- בדפדפן, עוברים אל דוגמאות WebRTC
getUserMedia
. - פותחים את המסוף.
- בודקים את המשתנה
stream
, שנמצא בהיקף גלובלי.
לכל MediaStream
יש קלט, שיכול להיות MediaStream
שנוצר על ידי getUserMedia()
, ופלט, שיכול להיות מועבר לרכיב וידאו או ל-RTCPeerConnection
.
השיטה getUserMedia()
מקבלת פרמטר של אובייקט MediaStreamConstraints
ומחזירה Promise
שמתמרה לאובייקט MediaStream
.
לכל MediaStream
יש label
, למשל 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'
. השיטה getAudioTracks()
והשיטה getVideoTracks()
מחזירות מערך של MediaStreamTrack
.
בדוגמה 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()
רק פעם אחת. בפעם הראשונה, יוצג לחצן 'אישור' בinfobar של הדפדפן. הגישה ל-HTTP עבור getUserMedia()
הוצאה משימוש ב-Chrome בסוף 2015 כי היא סווגה כתכונה חזקה.
הכוונה היא להפעיל את MediaStream
לכל מקור נתונים בסטרימינג, ולא רק למצלמה או למיקרופון. כך תוכלו להפעיל סטרימינג מנתונים שמאוחסנים או ממקורות נתונים שרירותיים, כמו חיישנים או מקורות קלט אחרים.
getUserMedia()
באמת מגיע לחיים בשילוב עם ספריות וממשקי API אחרים של JavaScript:
- Webcam Toy היא אפליקציית פוטו-בותי שמשתמשת ב-WebGL כדי להוסיף אפקטים מוזרים ומדהימים לתמונות, שאפשר לשתף או לשמור אותן באופן מקומי.
- FaceKat הוא משחק למעקב אחר הפנים שנוצר באמצעות headtrackr.js.
- האפליקציה ASCII Camera משתמשת ב-Canvas API כדי ליצור תמונות ASCII.
אילוצים
אפשר להשתמש באילוצים כדי להגדיר ערכים לרזולוציית הווידאו של getUserMedia()
. כך אפשר גם לתמוך באילוצים אחרים, כמו יחס גובה-רוחב, מצב צילום (מצלמה קדמית או אחורית), קצב פריימים, גובה ורוחב, וכן שיטת applyConstraints()
.
דוגמה לכך מופיעה בקטע דוגמאות WebRTC getUserMedia
: בחירת רזולוציה.
הגדרת ערך של אילוץ אסור גורמת להצגת הערך DOMException
או OverconstrainedError
, אם, לדוגמה, רזולוציה שהתבקשה לא זמינה. כדי לראות את זה בפעולה, אפשר לעיין בדמו בנושא דוגמאות ל-WebRTC getUserMedia
: בחירת רזולוציה.
צילום מסך וכרטיסייה
אפליקציות Chrome מאפשרות גם לשתף סרטון בשידור חי של כרטיסיית דפדפן אחת או של כל המסך באמצעות ממשקי ה-API chrome.tabCapture
ו-chrome.desktopCapture
. (דגמה ומידע נוסף זמינים במאמר שיתוף מסך באמצעות WebRTC. המאמר הזה נכתב לפני כמה שנים, אבל הוא עדיין מעניין).
אפשר גם להשתמש בצילום מסך כמקור MediaStream
ב-Chrome באמצעות האילוץ הניסיוני chromeMediaSource
. לתשומת ליבכם: כדי לצלם מסך צריך להשתמש ב-HTTPS, ואפשר להשתמש באפשרות הזו רק לצורכי פיתוח, כי היא מופעלת באמצעות דגל בשורת הפקודה, כפי שמוסבר בפוסט הזה.
איתות: בקרת סשנים, מידע על הרשת ועל המדיה
WebRTC משתמש ב-RTCPeerConnection
כדי להעביר נתוני סטרימינג בין דפדפנים (שנקראים גם עמיתים), אבל הוא זקוק גם למנגנון לתיאום התקשורת ולשליחת הודעות בקרה, תהליך שנקרא איתות. שיטות ופרוטוקולים של איתות לא מצוינים ב-WebRTC. איתותים הם לא חלק מ-API RTCPeerConnection
.
במקום זאת, מפתחי אפליקציות WebRTC יכולים לבחור את פרוטוקול ההודעות המועדף עליהם, כמו SIP או XMPP, ואת ערוץ התקשורת הדו-כיווני (duplex) המתאים. בדוגמה appr.tc נעשה שימוש ב-XHR וב-Channel API כמנגנון להעברת אותות. בcodelab נעשה שימוש ב-Socket.io שפועל ב-שרת Node.
האותות משמשים להעברת שלושה סוגים של מידע:
- הודעות לבקרת סשן: כדי לאתחל או לסגור את התקשורת ולדווח על שגיאות.
- הגדרת הרשת: מהן כתובת ה-IP והיציאה של המחשב שלכם בעולם החיצון?
- יכולות מדיה: אילו קודיקים ורזולוציות הדפדפן שלכם והדפדפן שהוא רוצה לתקשר איתו יכולים לטפל בהם?
כדי שאפשר יהיה להתחיל את הסטרימינג מ-peer-to-peer, חילופי המידע באמצעות איתותים צריכים להסתיים בהצלחה.
לדוגמה, נניח שאלי רוצה לתקשר עם בועז. לפניכם דוגמה לקוד ממפרט 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).
- עינת יוצרת אובייקט
RTCPeerConnection
עם טיפולonicecandidate
, שפועל כשמתקבלות רשימות של רשתות זמינות. - עינת שולחת לבועז נתוני מועמדים בסדרה דרך ערוץ האותות שבו הם משתמשים, כמו WebSocket או מנגנון אחר.
- כשבועז מקבל הודעת מועמדות מאילנה, הוא קורא לפונקציה
addIceCandidate
כדי להוסיף את המועמד לתיאור של השותף המרוחק.
לקוחות WebRTC (שנקראים גם עמיתים, או עינת ורון בדוגמה הזו) צריכים גם לקבוע ולשתף מידע מקומי ומרוחק על מדיה של אודיו ווידאו, כמו רזולוציה ויכולות של קודק. האות להעברת פרטי הגדרת המדיה מתבצע באמצעות החלפה של הצעה ותשובה באמצעות פרוטוקול תיאור הסשן (SDP):
- עינת מפעילה את השיטה
RTCPeerConnection
createOffer()
. הפונקציה מחזירה את הערךRTCSessionDescription
– תיאור הסשן המקומי של עינת. - בקריאה החוזרת, עינת מגדירה את התיאור המקומי באמצעות
setLocalDescription()
ואז שולחת את תיאור הסשן הזה לבועז דרך ערוץ האותות שלהם. שימו לב ש-RTCPeerConnection
לא יתחיל לאסוף מועמדים עד ש-setLocalDescription()
יקרא לו. הנושא הזה מקודד בטיוטת JSEP של IETF. - רון מגדיר את התיאור שאלי שלחה לו כתיאור המרוחק באמצעות
setRemoteDescription()
. - בוב מפעיל את השיטה
RTCPeerConnection
createAnswer()
, ומעביר לה את התיאור מרחוק שקיבל מענת כדי שיהיה אפשר ליצור סשן מקומי שתואם לסשן שלה. לפונקציית ההתקשרות החוזרתcreateAnswer()
מועברRTCSessionDescription
. בוב מגדיר את זה כתיאור המקומי ושולח אותו לאליס. - כשעינת מקבלת את תיאור הסשן של ירון, היא מגדירה אותו כתיאור המרוחק באמצעות
setRemoteDescription
. - פינג!
אובייקטים מסוג RTCSessionDescription
הם blobs שתואמים ל-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 Session Establishment Protocol (פרוטוקול ליצירת סשן ב-JavaScript), או JSEP. (יש אנימציה מצוינת שמסבירה את תהליך האותת והסטרימינג בסרטון הדגמה של Ericsson להטמעת WebRTC הראשונה שלה).
אחרי שתהליך האותות יושלם בהצלחה, אפשר להעביר נתונים בסטרימינג ישירות מאדם לאדם, בין מבצע הקריאה לבין הנמען – או, אם הניסיון הזה נכשל, דרך שרת מעבר (relay) ביניים (מידע נוסף על כך בהמשך). הסטרימינג הוא התפקיד של RTCPeerConnection
.
RTCPeerConnection
RTCPeerConnection
הוא הרכיב ב-WebRTC שמטפל בתקשורת יציבה ויעילה של נתוני סטרימינג בין עמיתים.
בתרשים הבא מוצגת ארכיטקטורת WebRTC עם התפקיד של RTCPeerConnection
. כפי שאפשר לראות, החלקים הירוקים מורכבים.
מנקודת מבט של JavaScript, הדבר העיקרי שצריך להבין מהתרשים הזה הוא ש-RTCPeerConnection
מגן על מפתחי האינטרנט מפני המורכבויות הרבות שמתחבאות מתחת לפני השטח. הקודקים והפרוטוקולים שבהם משתמש WebRTC מבצעים כמות עצומה של עבודה כדי לאפשר תקשורת בזמן אמת, גם ברשתות לא מהימנות:
- הסתרת אובדן מנות
- ביטול הד
- התאמה של רוחב הפס
- מאגר נתונים זמני דינמי של רעידות
- השגת שליטה באופן אוטומטי
- הפחתת רעש וביטול רעשים
- ניקוי תמונות
הקוד הקודם של W3C מציג דוגמה פשוטה של WebRTC מנקודת מבט של איתות. בהמשך מפורטות הדרכות לגבי שתי אפליקציות WebRTC שפועלות. הדוגמה הראשונה היא דוגמה פשוטה להדגמת RTCPeerConnection
, והדוגמה השנייה היא לקוח פעיל לשיחת וידאו.
RTCPeerConnection ללא שרתים
הקוד הבא לקוח מ-WebRTC samples Peer connection, שיש בו RTCPeerConnection
מקומי ו מרחוק (וכן וידאו מקומי ומרחוק) בדף אינטרנט אחד. זה לא משהו שימושי במיוחד – מבצע הקריאה והגורם שאליו היא נשלחת נמצאים באותו דף – אבל זה עוזר להבין קצת יותר טוב איך פועל ממשק ה-API של RTCPeerConnection
, כי אובייקטי RTCPeerConnection
בדף יכולים להחליף נתונים והודעות ישירות בלי להשתמש במנגנוני איתות ביניים.
בדוגמה הזו, pc1
מייצג את הצומת המקומי (המבצע של הקריאה) ו-pc2
מייצג את הצומת המרוחק (הנמען של הקריאה).
מתקשר
- יוצרים
RTCPeerConnection
חדש ומוסיפים את המקור מ-getUserMedia()
: ```js // Servers is an optional configuration file. (הסבר על TURN ו-STUN מופיע בהמשך). pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream); });
- יוצרים מבצע ומגדירים אותו כתיאור המקומי של
pc1
וכתיאור המרוחק שלpc2
. אפשר לעשות זאת ישירות בקוד בלי להשתמש בסימון, כי גם מבצע הקריאה וגם המקבל נמצאים באותו דף:js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );
מקבל הקריאה החוזרת
- יוצרים את
pc2
, וכשהשידור מ-pc1
יתווסף, מציגים אותו ברכיב וידאו:js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }
RTCPeerConnection
API ושרתי API
בעולם האמיתי, ל-WebRTC נדרשים שרתים, גם אם הם פשוטים, ולכן יכולים לקרות דברים כאלה:
- המשתמשים מגלים זה את זה ומחליפים פרטים מהעולם האמיתי, כמו שמות.
- אפליקציות לקוח של WebRTC (עמיתים) מחליפות נתוני רשת.
- הצמתים מחליפים נתונים על מדיה, כמו פורמט וידאו ורזולוציה.
- אפליקציות לקוח WebRTC עוברות דרך נתיבי NAT וחומות אש.
במילים אחרות, ל-WebRTC נדרשים ארבעה סוגים של פונקציונליות בצד השרת:
- גילוי משתמשים ותקשורת איתם
- איתות
- מעבר NAT/חומת אש
- שרתי העברה במקרה של כשל בתקשורת בין משתמשים
מעבר NAT, רשתות peer-to-peer והדרישות לפיתוח אפליקציית שרת לזיהוי משתמשים ולסימון אינן נכללות במאמר הזה. פרוטוקול STUN והתוסף שלו, TURN, משמשים את המסגרת ICE כדי לאפשר ל-RTCPeerConnection
להתמודד עם ניתוב NAT ועם תנודות אחרות ברשת.
ICE הוא מסגרת לחיבור בין עמיתים, כמו שני לקוחות של שיחות וידאו. בשלב הראשון, ה-ICE מנסה לחבר בין עמיתים ישירות עם זמן אחזור נמוך ככל האפשר באמצעות UDP. בתהליך הזה, שרתי STUN צריכים לבצע משימה אחת בלבד: לאפשר למשתמש שמאחורי NAT למצוא את הכתובת והיציאה הציבוריים שלו. (מידע נוסף על STUN ו-TURN זמין במאמר פיתוח שירותי הקצה העורפי הנדרשים לאפליקציית WebRTC).
אם הניסיון להשתמש ב-UDP נכשל, ה-ICE ינסה להשתמש ב-TCP. אם החיבור הישיר נכשל – במיוחד בגלל חומות אש ומעבר NAT בארגון – ה-ICE משתמש בשרת TURN (ממסר) ביניים. במילים אחרות, ה-ICE משתמש קודם ב-STUN עם UDP כדי לחבר ישירות בין עמיתים, ואם הניסיון הזה נכשל, הוא עובר לשרתי ממסר מסוג TURN. הביטוי חיפוש מועמדים מתייחס לתהליך של חיפוש ממשקי רשת ויציאות.
מהנדס WebRTC, ג'סטין אוברטי, מספק מידע נוסף על ICE, STUN ו-TURN במצגת WebRTC מ-Google I/O 2013. (במצגת מפורטות דוגמאות להטמעות של שרתים מסוג TURN ו-STUN).
לקוח פשוט לשיחות וידאו
מקום טוב לנסות את WebRTC, עם איתות וניתוב NAT/חומת אש באמצעות שרת STUN, הוא הדמו של שיחת הווידאו בכתובת appr.tc. האפליקציה הזו משתמשת ב-adapter.js, תוסף שמבודד אפליקציות משינויים במפרט ומהבדלים בקידומות.
הקוד מפורט בכוונה ביומן. כדאי לבדוק במסוף את סדר האירועים. בהמשך מופיע הסבר מפורט על הקוד.
טופולוגיות רשת
WebRTC, כפי שהוא מיושם כרגע, תומך רק בתקשורת 'אחד על אחד', אבל אפשר להשתמש בו בתרחישי רשת מורכבים יותר, למשל עם כמה משתמשים שכל אחד מהם מתקשר עם השניים האחרים ישירות או דרך יחידת בקרה מרובה נקודות (MCU), שרת שיכול לטפל במספר גדול של משתתפים ולבצע העברה סלקטיבית של שידורים, ערבוב או הקלטה של אודיו ווידאו.
אפליקציות WebRTC רבות קיימות רק כדי להדגים תקשורת בין דפדפני אינטרנט, אבל שרתי שער יכולים לאפשר לאפליקציית WebRTC שפועלת בדפדפן לקיים אינטראקציה עם מכשירים, כמו טלפונים (שנקראים גם PSTN) ועם מערכות VOIP. במאי 2012, Doubango Telecom פרסמה בקוד פתוח את sipml5 SIP client שנוצר באמצעות WebRTC ו-WebSocket, ומאפשר (בין יתר השימושים האפשריים) שיחות וידאו בין דפדפנים לאפליקציות שפועלות ב-iOS וב-Android. ב-Google I/O, Tethr ו-Tropo הדגימו מסגרת לתקשורת במקרי אסון בתיקי גב באמצעות תא OpenBTS, כדי לאפשר תקשורת בין טלפונים עם תכונות בסיסיות למחשבים באמצעות WebRTC. תקשורת טלפון ללא ספק!
RTCDataChannel
API<
בנוסף לאודיו ולווידאו, WebRTC תומך בתקשורת בזמן אמת לסוגים אחרים של נתונים.
ה-API של RTCDataChannel
מאפשר החלפה של נתונים שרירותיים בין מחשבים עם זמן אחזור נמוך וזרימה גבוהה. כדי לראות הדגמות בדף אחד ולקבל מידע על פיתוח אפליקציה פשוטה להעברת קבצים, אפשר לעיין בדוגמאות ל-WebRTC ובcodelab של WebRTC, בהתאמה.
יש הרבה תרחישים לדוגמה שבהם אפשר להשתמש ב-API, כולל:
- משחקים
- אפליקציות של מחשב מרוחק
- צ'אט טקסט בזמן אמת
- העברת קבצים
- רשתות מבוזרות
לממשק ה-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, גם אם נדרש שרת ממסר (TURN) כשהחורים נקדחים כדי להתמודד עם חומות אש ו-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 מאפשרים ליצור כלים ליצירת תוכן ולתקשורת באופן דמוקרטי ומבוזר, כולל טלפוניה, משחקים, הפקת סרטונים, יצירת מוזיקה ואיסוף חדשות.
קשה למצוא טכנולוגיה מרחיקה לכת יותר מזו.
כפי שניסח זאת הבלוגר Phil Edholm, "יכול להיות ש-WebRTC ו-HTML5 יאפשרו את אותה טרנספורמציה לתקשורת בזמן אמת שהדפדפן המקורי אפשר למידע".
כלים למפתחים
- הנתונים הסטטיסטיים של WebRTC לגבי סשן מתמשך זמינים בכתובת:
- about://webrtc-internals ב-Chrome
- opera://webrtc-internals ב-Opera
- about:webrtc ב-Firefox
- הערות לגבי יכולת פעולה הדדית בדפדפנים שונים
- adapter.js הוא תוסף JavaScript ל-WebRTC שמנוהל על ידי Google בעזרת קהילת WebRTC, ומספק אבסטרקציה של תחיליות של ספקים, הבדלים בדפדפנים ושינויים במפרט.
- מידע נוסף על תהליכי האותות של WebRTC זמין בפלט היומן appr.tc בקונסולה.
- אם זה נראה לכם מסובך מדי, אולי כדאי להשתמש במסגרת WebRTC או אפילו בשירות WebRTC מלא.
- אנחנו תמיד מקבלים בברכה דיווחים על באגים ובקשות להוספת תכונות:
מידע נוסף
- הרצאה של Justin Uberti בנושא WebRTC ב-Google I/O 2012
- Alan B. Johnston ו-Daniel C. בורנט מנהל ספר על WebRTC, שזו המהדורה השלישית שלו, בפורמטים מודפסים ודיגיטליים בכתובת webrtcbook.com.
- באתר webrtc.org אפשר למצוא את כל מה שקשור ל-WebRTC, כולל הדגמות, מסמכי עזרה ודיונים.
- discuss-webrtc היא קבוצת Google לדיון טכני בנושא WebRTC.
- @webrtc
- במסמכי התיעוד של Google Developers ב-Talk מפורט מידע נוסף על ניתוב NAT, STUN, שרתי ממסר ואיסוף מועמדים.
- WebRTC ב-GitHub
- Stack Overflow הוא מקום טוב לחפש בו תשובות ולשאול שאלות על WebRTC.
תקנים ופרוטוקולים
- טיוטת ה-Editor's Draft של WebRTC ב-W3C
- טיוטת עורכים של W3C: צילום מדיה וסטרימינג (נקראת גם
getUserMedia
) - IETF Working Group Charter
- טיוטת פרוטוקול של IETF WebRTC Data Channel
- טיוטת JSEP של IETF
- תקן מוצע של IETF ל-ICE
- טיוטת אינטרנט של קבוצת העבודה IETF RTCWEB: תרחישים לדוגמה ודרישות לתקשורת בזמן אמת באינטרנט
סיכום התמיכה ב-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 ואילך
RTCPeerConnection
API
- 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 ואילך
RTCDataChannel
API
- גרסה ניסיונית ב-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.