بدء استخدام WebRTC

تمثّل WebRTC جبهة جديدة في الحرب الطويلة من أجل شبكة إنترنت مفتوحة وبدون قيود.

بريندان آيش، مبتكر JavaScript

التواصل في الوقت الفعلي بدون استخدام مكوّنات إضافية

تخيَّل عالمًا يمكن فيه لهاتفك وتلفزيونك وجهاز الكمبيوتر التواصل على منصة مشتركة. تخيّل لو كان من السهل إضافة محادثة فيديو ومشاركة البيانات بين الأجهزة إلى تطبيق الويب. هذا هو الهدف من WebRTC.

أيهمّك تجربة الميزة؟ تتوفّر WebRTC على أجهزة الكمبيوتر والأجهزة الجوّالة في متصفّحات Google Chrome وSafari وFirefox وOpera. يمكنك البدء باستخدام تطبيق محادثة الفيديو البسيط على appr.tc:

  1. افتح appr.tc في المتصفّح.
  2. انقر على انضمام للانضمام إلى غرفة محادثة والسماح للتطبيق باستخدام كاميرا الويب.
  3. افتح عنوان URL المعروض في نهاية الصفحة في علامة تبويب جديدة أو على جهاز كمبيوتر آخر.

البدء بسرعة

ليس لديك وقت لقراءة هذه المقالة أو تريد الحصول على الرمز فقط؟

بدلاً من ذلك، يمكنك الانتقال مباشرةً إلى الدرس التطبيقي حول WebRTC، وهو دليل مفصّل يشرح كيفية إنشاء تطبيق كامل لمحادثة الفيديو، بما في ذلك خادم إرسال إشارات بسيط.

لمحة موجزة عن تاريخ WebRTC

أحد آخر التحديات الرئيسية التي تواجه الويب هو إتاحة التواصل بين الأشخاص من خلال الصوت والفيديو، أي التواصل في الوقت الفعلي (RTC) باختصار. يجب أن تكون ميزة "الاتصال في الوقت الفعلي" طبيعية في تطبيق الويب مثل إدخال نص في حقل إدخال نص. وبدونه، ستكون قدرتك محدودة على الابتكار وتطوير طرق جديدة للتفاعل مع المستخدمين.

في السابق، كانت تقنية الاتصال في الوقت الفعلي (RTC) مخصّصة للشركات ومعقّدة، وكانت تتطلّب ترخيص تقنيات صوت وفيديو باهظة الثمن أو تطويرها داخليًا. كان دمج تكنولوجيا الاتصال في الوقت الفعلي مع المحتوى والبيانات والخدمات الحالية أمرًا صعبًا ويستغرق وقتًا طويلاً، لا سيما على الويب.

أصبحت محادثات الفيديو في Gmail رائجة في عام 2008، وفي عام 2011، قدّمت Google تطبيق Hangouts الذي يستخدم Talk (كما كان يفعل Gmail). اشترت Google شركة GIPS التي طوّرت العديد من المكوّنات المطلوبة للاتصال في الوقت الفعلي، مثل برامج الترميز وتقنيات إلغاء الصدى. أتاحت Google المصدر المفتوح للتكنولوجيات التي طوّرها فريق GIPS، وتعاونت مع هيئات المعايير ذات الصلة في "فريق مهندسي شبكة الإنترنت" (IETF) و"اتحاد شبكة الويب العالمية" (W3C) لضمان توافق آراء المجال. في أيار (مايو) 2011، أنشأت شركة "إريكسون" أول تطبيق لتقنية WebRTC.

تطبّق WebRTC معايير مفتوحة للاتصال في الوقت الفعلي بالفيديو والصوت والبيانات بدون الحاجة إلى استخدام أي مكوّنات إضافية. كانت الحاجة حقيقية:

  • استخدمت العديد من خدمات الويب تقنية RTC، ولكن كان يجب تنزيل تطبيقات أو مكوّنات إضافية. وشملت هذه التطبيقات Skype وFacebook وHangouts.
  • تنزيل المكوّنات الإضافية وتثبيتها وتحديثها أمر معقّد وعُرضة للأخطاء ومزعج.
  • من الصعب نشر المكوّنات الإضافية وتصحيح أخطائها وتحديد المشاكل فيها وحلّها واختبارها وصيانتها، وقد تتطلّب ترخيصًا وتكاملاً مع تكنولوجيا معقّدة ومكلفة. في كثير من الأحيان، يكون من الصعب إقناع المستخدمين بتثبيت الإضافات في المقام الأول.

تتمثّل المبادئ التوجيهية لمشروع WebRTC في أنّ واجهات برمجة التطبيقات يجب أن تكون مفتوحة المصدر ومجانية وموحّدة ومعيارية ومضمّنة في متصفّحات الويب وأكثر فعالية من التقنيات الحالية.

ما هو وضعنا الحالي؟

يتم استخدام WebRTC في تطبيقات مختلفة، مثل Google Meet. تم أيضًا دمج WebRTC مع WebKitGTK+ وتطبيقات Qt الأصلية.

تنفّذ WebRTC واجهات برمجة التطبيقات الثلاث التالية: - MediaStream (المعروفة أيضًا باسم getUserMedia) - RTCPeerConnection - RTCDataChannel

يتم تحديد واجهات برمجة التطبيقات في هاتين المواصفاتين:

تتوافق واجهات برمجة التطبيقات الثلاث مع الأجهزة الجوّالة وأجهزة الكمبيوتر المكتبي على متصفّحات Chrome وSafari وFirefox وEdge وOpera.

getUserMedia: للاطّلاع على العروض التوضيحية والرموز، يمكنك الرجوع إلى أمثلة WebRTC أو تجربة الأمثلة الرائعة التي أعدّها Chris Wilson وتستخدم getUserMedia كإدخال للصوت على الويب.

RTCPeerConnection: للحصول على عرض توضيحي بسيط وتطبيق دردشة فيديو يعمل بكامل وظائفه، يمكنك الاطّلاع على عينات WebRTC: اتصال الند للند وappr.tc على التوالي. يستخدم هذا التطبيق adapter.js، وهو برنامج وسيط JavaScript تحتفظ به Google بمساعدة منتدى WebRTC، وذلك لإخفاء الاختلافات بين المتصفحات والتغييرات في المواصفات.

RTCDataChannel: للاطّلاع على هذا الإجراء، يمكنك مراجعة عينات WebRTC للاطّلاع على أحد العروض التوضيحية لقنوات البيانات.

يوضّح الدرس التطبيقي حول WebRTC كيفية استخدام جميع واجهات برمجة التطبيقات الثلاث لإنشاء تطبيق بسيط لمحادثة الفيديو ومشاركة الملفات.

أول WebRTC

يجب أن تنفّذ تطبيقات WebRTC عدة إجراءات، وهي:

  • الحصول على بيانات صوتية أو فيديو أو غير ذلك من البيانات
  • الحصول على معلومات الشبكة، مثل عناوين IP والمنافذ، وتبادلها مع برامج WebRTC أخرى (تُعرف باسم الأجهزة النظيرة) لإتاحة الاتصال، حتى من خلال ترجمة عناوين الشبكة وجدران الحماية
  • تنسيق عملية تبادل الإشارات للإبلاغ عن الأخطاء وبدء الجلسات أو إغلاقها
  • تبادل المعلومات حول الوسائط وإمكانات العميل، مثل الدقة وبرامج الترميز
  • إرسال الصوت أو الفيديو أو البيانات عبر البث

للحصول على بيانات البث والتواصل معها، تنفّذ WebRTC واجهات برمجة التطبيقات التالية:

  • يتم منح MediaStream إذن الوصول إلى مصادر البيانات، مثل الكاميرا والميكروفون في جهاز المستخدم.
  • تتيح RTCPeerConnection إجراء مكالمات صوتية أو مكالمات فيديو مع توفير تسهيلات للتشفير وإدارة معدل نقل البيانات.
  • تتيح RTCDataChannel تبادل البيانات العامة بين الأجهزة مباشرةً.

(سنتناول لاحقًا مناقشة تفصيلية لجوانب الشبكة والإشارات في WebRTC).

MediaStream واجهة برمجة التطبيقات (المعروفة أيضًا باسم getUserMedia API)

تمثّل واجهة برمجة التطبيقات MediaStream تدفّقات الوسائط المتزامنة. على سبيل المثال، يتضمّن البث المأخوذ من الكاميرا والميكروفون مسارات فيديو وصوت متزامنة. (يُرجى عدم الخلط بين MediaStreamTrack والعنصر <track>، فهما مختلفان تمامًا).

ربما تكون أسهل طريقة لفهم واجهة برمجة التطبيقات MediaStream هي إلقاء نظرة عليها في بيئتها الطبيعية:

  1. في المتصفّح، انتقِل إلى أمثلة WebRTC getUserMedia.
  2. افتح وحدة التحكّم.
  3. افحص المتغير stream الذي يقع في النطاق العمومي.

يتضمّن كل MediaStream مدخلاً، قد يكون MediaStream من إنشاء getUserMedia()، ومخرجًا، قد يتم تمريره إلى عنصر فيديو أو RTCPeerConnection.

تأخذ الطريقة getUserMedia() مَعلمة كائن MediaStreamConstraints وتعرض Promise يتم تحويله إلى كائن MediaStream.

لكل MediaStream label، مثل 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'. يتم عرض مصفوفة من MediaStreamTracks بواسطة الطريقتَين 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(). في المرة الأولى، يظهر زر "السماح" في شريط المعلومات في المتصفّح. أوقف Chrome نهائيًا إمكانية الوصول إلى getUserMedia() عبر HTTP في نهاية عام 2015 لأنّه تم تصنيفه على أنّه ميزة قوية.

والهدف من ذلك هو إتاحة MediaStream لأي مصدر بيانات بث، وليس فقط الكاميرا أو الميكروفون. سيؤدي ذلك إلى إتاحة البث من البيانات المخزَّنة أو مصادر البيانات العشوائية، مثل أجهزة الاستشعار أو المدخلات الأخرى.

تتضح أهمية getUserMedia() عند استخدامها مع واجهات برمجة تطبيقات ومكتبات JavaScript الأخرى:

  • Webcam Toy هو تطبيق كشك صور يستخدم WebGL لإضافة تأثيرات غريبة ورائعة إلى الصور التي يمكن مشاركتها أو حفظها على الجهاز.
  • FaceKat هي لعبة لتتبُّع الوجه تم إنشاؤها باستخدام headtrackr.js.
  • تستخدم إضافة ASCII Camera واجهة برمجة التطبيقات Canvas API لإنشاء صور ASCII.
صورة ASCII من إنشاء idevelop.ro/ascii-camera
gUM ASCII art!

القيود

يمكن استخدام القيود لضبط قيم درجة دقة الفيديو في getUserMedia(). يتيح ذلك أيضًا إمكانية استخدام قيود أخرى، مثل نسبة العرض إلى الارتفاع ووضع الكاميرا (أمامية أو خلفية) وعدد اللقطات في الثانية والارتفاع والعرض وطريقة applyConstraints().

للاطّلاع على مثال، يُرجى الانتقال إلى أمثلة WebRTC getUserMedia: اختيار الدقة.

يؤدي ضبط قيمة غير مسموح بها للقيود إلى عرض الخطأ DOMException أو OverconstrainedError، مثلاً إذا لم تكن الدقة المطلوبة متاحة. لمشاهدة هذا الإجراء، يمكنك الاطّلاع على عينات WebRTC getUserMedia: اختيار الدقة للحصول على عرض توضيحي.

تسجيل الشاشة وعلامة التبويب

تتيح تطبيقات Chrome أيضًا مشاركة فيديو مباشر لعلامة تبويب واحدة في المتصفّح أو سطح المكتب بالكامل من خلال واجهتَي برمجة التطبيقات chrome.tabCapture وchrome.desktopCapture. (للحصول على عرض توضيحي والمزيد من المعلومات، يمكنك الاطّلاع على مشاركة الشاشة باستخدام WebRTC. المقالة قديمة بعض الشيء، ولكنها لا تزال مثيرة للاهتمام.)

يمكن أيضًا استخدام ميزة "التقاط الشاشة" كمصدر MediaStream في Chrome باستخدام القيد التجريبي chromeMediaSource. يُرجى العِلم أنّ ميزة "التقاط الشاشة" تتطلّب استخدام بروتوكول HTTPS ويجب استخدامها فقط لأغراض التطوير لأنّها مفعّلة من خلال علامة سطر الأوامر كما هو موضّح في هذه المشاركة.

الإشارات: التحكّم في الجلسة والشبكة ومعلومات الوسائط

تستخدم WebRTC بروتوكول RTCPeerConnection لتوصيل بيانات البث بين المتصفّحات (المعروفة أيضًا باسم الأجهزة النظيرة)، ولكنها تحتاج أيضًا إلى آلية لتنسيق الاتصال وإرسال رسائل التحكّم، وهي عملية تُعرف باسم الإشارة. لا يحدّد WebRTC أساليب وبروتوكولات الإشارات. لا يشكّل إرسال الإشارات جزءًا من واجهة برمجة التطبيقات RTCPeerConnection.

بدلاً من ذلك، يمكن لمطوّري تطبيقات WebRTC اختيار بروتوكول المراسلة الذي يفضّلونه، مثل SIP أو XMPP، وأي قناة اتصال مناسبة ثنائية الاتجاه. يستخدم مثال appr.tc XHR وChannel API كآلية إرسال الإشارات. يستخدم codelab Socket.io الذي يعمل على خادم Node.

تُستخدَم الإشارات لتبادل ثلاثة أنواع من المعلومات:

  • رسائل التحكّم في الجلسة: لتهيئة الاتصال أو إغلاقه والإبلاغ عن الأخطاء
  • إعدادات الشبكة: ما هو عنوان IP والمنفذ الخاصان بجهاز الكمبيوتر بالنسبة إلى العالم الخارجي؟
  • إمكانات الوسائط: ما هي برامج الترميز والدقة التي يمكن أن يتعامل معها متصفّحك والمتصفّح الذي يريد التواصل معه؟

يجب أن يكتمل تبادل المعلومات من خلال الإشارات بنجاح قبل أن يبدأ البث من نظير إلى نظير.

على سبيل المثال، لنفترض أنّ "سارة" تريد التواصل مع "علي". في ما يلي نموذج رمز من مواصفات W3C WebRTC، يوضّح عملية الإشارة أثناء التنفيذ. يفترض الرمز البرمجي وجود آلية إرسال إشارات تم إنشاؤها في الطريقة createSignalingChannel(). يُرجى أيضًا العِلم أنّه يتم حاليًا إضافة البادئة RTCPeerConnection إلى الروابط على متصفّحَي Chrome وOpera.

// 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 باستخدام معالج onicecandidate، والذي يتم تنفيذه عندما تصبح المرشحات المتاحة للشبكة متاحة.
  2. ترسل "أليس" بيانات المرشّح المتسلسلة إلى "بوب" من خلال أي قناة إرسال إشارات يستخدمانها، مثل WebSocket أو آلية أخرى.
  3. عندما يتلقّى "بوب" رسالة مرشّح من "أليس"، يتّصل بـ addIceCandidate لإضافة المرشّح إلى وصف النظير البعيد.

يحتاج عملاء WebRTC (المعروفون أيضًا باسم الأجهزة النظيرة، أو "أليس" و"بوب" في هذا المثال) أيضًا إلى التأكّد من معلومات وسائط الصوت والفيديو المحلية والبعيدة وتبادلها، مثل دقة الشاشة وإمكانات الترميز. يتم تبادل معلومات إعداد الوسائط من خلال تبادل عرض ورد باستخدام بروتوكول وصف الجلسة (SDP):

  1. تنفّذ "سارة" الطريقة RTCPeerConnection createOffer(). يتم تمرير العائد من هذا RTCSessionDescription - وصف جلسة "أليس" المحلية.
  2. في دالة الاستدعاء، تضبط "أليس" الوصف المحلي باستخدام setLocalDescription() ثم ترسل وصف الجلسة هذا إلى "بوب" من خلال قناة الإشارات. يُرجى العِلم أنّ RTCPeerConnection لن تبدأ في جمع المرشّحين إلى أن يتم استدعاء setLocalDescription(). تم تدوين ذلك في مسودة JSEP IETF.
  3. يضبط يوسف الوصف الذي أرسلته إليه نبيلة كوصف عن بُعد باستخدام setRemoteDescription().
  4. ينفّذ "بوب" الطريقة RTCPeerConnection createAnswer()، ويمرّر إليها الوصف البعيد الذي حصل عليه من "أليس" حتى يمكن إنشاء جلسة محلية متوافقة مع جلستها. يتم تمرير RTCSessionDescription إلى دالة رد الاتصال createAnswer(). يضبط "بوب" هذا الوصف كالوصف المحلي ويرسله إلى "أليس".
  5. عندما تتلقّى "أليس" وصف جلسة "بوب"، تحدّد هذا الوصف كوصف عن بُعد باستخدام setRemoteDescription.
  6. Ping!

عناصر RTCSessionDescription هي كائنات ثنائية كبيرة الحجم تتوافق مع بروتوكول وصف الجلسة، 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. (يتوفّر رسم متحرك ممتاز يشرح عملية الإشارة والبث في فيديو العرض التوضيحي من Ericsson لأول عملية تنفيذ لبروتوكول WebRTC).

مخطّط بنية JSEP
بنية JSEP

بعد اكتمال عملية إرسال الإشارات بنجاح، يمكن بث البيانات مباشرةً من نظير إلى نظير بين المتصل والمتلقي، أو من خلال خادم وسيط (سنتحدّث عن ذلك لاحقًا) في حال تعذّر ذلك. RTCPeerConnection هو المسؤول عن البث.

RTCPeerConnection

RTCPeerConnection هو أحد مكونات WebRTC الذي يتعامل مع الاتصال الثابت والفعّال للبيانات المتدفقة بين الأجهزة.

في ما يلي رسم بياني لبنية WebRTC يوضّح دور RTCPeerConnection. وكما ستلاحظ، فإنّ الأجزاء الخضراء معقّدة.

مخطط بنية WebRTC
بنية WebRTC (من webrtc.org)

من منظور JavaScript، الشيء الرئيسي الذي يجب فهمه من هذا الرسم البياني هو أنّ RTCPeerConnection يحمي مطوّري الويب من التعقيدات العديدة التي تكمن في الأسفل. تؤدي برامج الترميز والبروتوكولات التي تستخدمها WebRTC الكثير من العمل لإتاحة الاتصال في الوقت الفعلي، حتى عبر الشبكات غير الموثوق بها:

  • إخفاء فقدان الحزمة
  • إلغاء الصدى
  • التكيّف مع معدل نقل البيانات
  • التخزين المؤقت الديناميكي غير المستقر
  • التحكم الآلي في الصوت
  • تقليل الضوضاء وكتمها
  • تنظيف الصور

يعرض رمز W3C السابق مثالاً مبسطًا على WebRTC من منظور الإشارات. في ما يلي شرح تفصيلي لتطبيقَين يعملان باستخدام WebRTC. الأول هو مثال بسيط لتوضيح RTCPeerConnection والثاني هو برنامج دردشة فيديو يعمل بكامل طاقته.

RTCPeerConnection بدون خوادم

تم أخذ الرمز التالي من عينات WebRTC الخاصة باتصال الند للند، والتي تتضمّن وRTCPeerConnection محليًا (وفيديو محليًا وعن بُعد) على صفحة ويب واحدة. لا يشكّل هذا أي شيء مفيد جدًا، فالمتصل والمتلقي موجودان على الصفحة نفسها، ولكنّه يوضّح طريقة عمل واجهة برمجة التطبيقات RTCPeerConnection قليلاً لأنّ عناصر RTCPeerConnection على الصفحة يمكنها تبادل البيانات والرسائل مباشرةً بدون الحاجة إلى استخدام آليات إرسال الإشارات الوسيطة.

في هذا المثال، يمثّل pc1 الجهاز المحلي (المتصل) ويمثّل pc2 الجهاز البعيد (المتلقّي).

المُتصِل

  1. أنشئ RTCPeerConnection جديدًا وأضِف إليه البث من getUserMedia(): ```js // Servers is an optional configuration file. (يمكنك الاطّلاع على مناقشة TURN وSTUN لاحقًا.) pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { 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 );

Callee

  1. أنشئوا pc2، وعند إضافة البث من pc1، اعرضوه في عنصر فيديو: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection واجهة برمجة التطبيقات بالإضافة إلى الخوادم

في العالم الحقيقي، تحتاج WebRTC إلى خوادم، مهما كانت بسيطة، حتى يمكن تنفيذ ما يلي:

  • يتعرّف المستخدمون على بعضهم البعض ويتبادلون التفاصيل الواقعية، مثل الأسماء.
  • تتبادل تطبيقات عميل WebRTC (الأجهزة النظيرة) معلومات الشبكة.
  • يتبادل المستخدمون بيانات حول الوسائط، مثل تنسيق الفيديو ودرجة الدقة.
  • تتجاوز تطبيقات عميل WebRTC بوابات NAT وجدران الحماية.

بعبارة أخرى، تحتاج WebRTC إلى أربعة أنواع من الوظائف من جهة الخادم:

  • اكتشاف المستخدمين والتواصل معهم
  • إرسال الإشارات
  • اجتياز NAT/جدار الحماية
  • خوادم الترحيل في حال تعذُّر التواصل بين الأجهزة مباشرةً

إنّ اجتياز NAT والشبكات من نظير إلى نظير ومتطلبات إنشاء تطبيق خادم لاكتشاف المستخدمين وإرسال الإشارات تتجاوز نطاق هذه المقالة. يكفي القول إنّ بروتوكول STUN وإضافته TURN يستخدمهما إطار عمل ICE لتمكين RTCPeerConnection من التعامل مع اجتياز NAT وغيرها من تقلبات الشبكة.

‫ICE هو إطار عمل لربط الأجهزة المتصلة بالشبكة، مثل جهازَي عميل لدردشة الفيديو. في البداية، يحاول بروتوكول ICE ربط الأجهزة النظيرة مباشرةً بأقل وقت استجابة ممكن من خلال بروتوكول UDP. في هذه العملية، يكون لخوادم STUN مهمة واحدة، وهي السماح لجهاز نظير خلف NAT بمعرفة عنوانه ومنفذه العلنيَّين. (لمزيد من المعلومات عن STUN وTURN، يُرجى الاطّلاع على إنشاء خدمات الخلفية اللازمة لتطبيق WebRTC).

العثور على مصادر مُرشَّحة للاتصال
العثور على مستخدمين مقترحين للتواصل

إذا تعذّر استخدام UDP، يحاول ICE استخدام TCP. في حال تعذُّر الاتصال المباشر، لا سيما بسبب اجتياز NAT وجدران الحماية في المؤسسات، يستخدم بروتوكول ICE خادم TURN وسيطًا (خادم إرسال). بعبارة أخرى، تستخدم ICE أولاً STUN مع UDP لربط الأجهزة النظيرة مباشرةً، وإذا تعذّر ذلك، تعود إلى خادم ترحيل TURN. يشير التعبير العثور على المرشّحين إلى عملية العثور على منافذ وواجهات شبكة.

مسارات بيانات WebRTC
مسارات بيانات WebRTC

يقدّم مهندس WebRTC، جاستن أوبيرتي، المزيد من المعلومات حول ICE وSTUN وTURN في عرض WebRTC التقديمي في مؤتمر Google I/O لعام 2013. (تقدّم شرائح العرض التقديمي أمثلة على عمليات تنفيذ خادمَي TURN وSTUN).

برنامج بسيط لمحادثات الفيديو

يُعدّ عرض الفيديو التوضيحي للدردشة على appr.tc مكانًا جيدًا لتجربة WebRTC، وهو يتضمّن إشارات واجتياز NAT/جدار الحماية باستخدام خادم STUN. يستخدم هذا التطبيق adapter.js، وهو برنامج وسيط لعزل التطبيقات عن تغييرات المواصفات واختلافات البادئة.

الرمز مطوّل بشكل متعمّد في تسجيلاته. راجِع وحدة التحكّم لفهم ترتيب الأحداث. في ما يلي شرح تفصيلي للرمز البرمجي.

تصاميم الشبكات

لا يتيح WebRTC، كما هو مطبّق حاليًا، سوى التواصل بين شخصين، ولكن يمكن استخدامه في سيناريوهات شبكات أكثر تعقيدًا، مثل التواصل بين عدة أجهزة مباشرةً أو من خلال وحدة تحكّم متعددة النقاط (MCU)، وهي خادم يمكنه التعامل مع أعداد كبيرة من المشاركين وتنفيذ عمليات إعادة توجيه انتقائية للبث، بالإضافة إلى دمج الصوت والفيديو أو تسجيلهما.

مخطّط طوبولوجيا لوحدة تحكّم متعددة النقاط
مثال على بنية وحدة التحكّم المتعدّدة النقاط

تتيح العديد من تطبيقات WebRTC الحالية التواصل بين متصفّحات الويب فقط، ولكن يمكن لخوادم البوابة أن تتيح لتطبيق WebRTC الذي يعمل على متصفّح التفاعل مع أجهزة مثل الهواتف (المعروفة أيضًا باسم PSTN) وأنظمة VOIP. في أيار (مايو) 2012، أتاحت شركة Doubango Telecom المصدر المفتوح لبرنامج sipml5 SIP الذي تم إنشاؤه باستخدام WebRTC وWebSocket، والذي يتيح (من بين الاستخدامات المحتملة الأخرى) إجراء مكالمات فيديو بين المتصفحات والتطبيقات التي تعمل على iOS وAndroid. في مؤتمر Google I/O، عرضت شركتا Tethr وTropo إطار عمل للاتصالات في حالات الكوارث في حقيبة باستخدام خلية OpenBTS لإتاحة الاتصالات بين الهواتف العادية وأجهزة الكمبيوتر من خلال WebRTC. التواصل عبر الهاتف بدون مشغّل شبكة جوّال

عرض توضيحي لخدمة Tethr/Tropo في مؤتمر Google I/O لعام 2012
Tethr/Tropo: اتصالات مواجهة الأزمات في حقيبة

RTCDataChannel واجهة برمجة التطبيقات<

بالإضافة إلى الصوت والفيديو، تتيح WebRTC الاتصال في الوقت الفعلي لأنواع أخرى من البيانات.

تتيح واجهة برمجة التطبيقات RTCDataChannel تبادُل البيانات العشوائية بين الأجهزة بسرعة استجابة منخفضة ومعدّل نقل بيانات مرتفع. للاطّلاع على عروض توضيحية من صفحة واحدة ومعرفة كيفية إنشاء تطبيق بسيط لنقل الملفات، يمكنك الاطّلاع على نماذج WebRTC والدرس التطبيقي حول WebRTC على التوالي.

هناك العديد من حالات الاستخدام المحتملة لواجهة برمجة التطبيقات، بما في ذلك:

  • ألعاب فيديو
  • تطبيقات الاتصال عن بُعد
  • الدردشة النصية في الوقت الفعلي
  • نقل الملفات
  • الشبكات غير المركزية

تتضمّن واجهة برمجة التطبيقات عدة ميزات للاستفادة إلى أقصى حدّ من 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) مطلوبًا عند فشل عملية ثقب الجدار الناري للتعامل مع جدران الحماية وعمليات ترجمة عناوين الشبكة (NAT).

تتوفّر RTCDataChannel في متصفّحات Chrome وSafari وFirefox وOpera وSamsung Internet. تستخدم لعبة Cube Slam واجهة برمجة التطبيقات للتواصل بشأن حالة اللعبة. العب مع صديق أو العب دور الدب أتاحت المنصة المبتكرة Sharefest مشاركة الملفات من خلال RTCDataChannel، وقدّمت peerCDN لمحة عن كيفية إتاحة WebRTC لتوزيع المحتوى من نظير إلى نظير.

لمزيد من المعلومات حول RTCDataChannel، يمكنك الاطّلاع على مسودة مواصفات البروتوكول الصادرة عن فريق عمل هندسة الإنترنت (IETF).

الأمان

هناك عدة طرق يمكن أن يؤدي بها تطبيق أو مكوّن إضافي للاتصال في الوقت الفعلي إلى تعريض الأمان للخطر. على سبيل المثال:

  • قد يتم اعتراض الوسائط أو البيانات غير المشفرة بين المتصفحات أو بين المتصفح والخادم.
  • قد يسجّل تطبيق فيديو أو صوتًا ويوزّعهما بدون علم المستخدم.
  • قد يتم تثبيت برامج ضارة أو فيروسات مع مكوّن إضافي أو تطبيق يبدو غير ضار.

تتضمّن WebRTC عدة ميزات لتجنُّب هذه المشاكل:

  • تستخدم عمليات تنفيذ WebRTC بروتوكولات آمنة، مثل DTLS وSRTP.
  • التشفير إلزامي لجميع مكونات WebRTC، بما في ذلك آليات الإشارة.
  • WebRTC ليس مكوّنًا إضافيًا. يتم تشغيل مكوناته في بيئة الاختبار المعزولة للمتصفح وليس في عملية منفصلة. لا تتطلّب المكوّنات تثبيتًا منفصلاً ويتم تحديثها كلّما تم تحديث المتصفّح.
  • يجب منح إذن الوصول إلى الكاميرا والميكروفون بشكل صريح، وعند تشغيلهما، توضّح واجهة المستخدم ذلك بشكل واضح.

لا تتناول هذه المقالة مناقشة كاملة لأمان وسائط البث. لمزيد من المعلومات، يُرجى الاطّلاع على بنية أمان WebRTC المقترَحة التي اقترحتها "فريق عمل هندسة الإنترنت" (IETF).

الخلاصة

يمكن أن تساهم واجهات برمجة التطبيقات ومعايير WebRTC في إتاحة أدوات إنشاء المحتوى والتواصل للجميع وتوزيعها على نطاق واسع، بما في ذلك الاتصالات الهاتفية والألعاب وإنتاج الفيديو وصناعة الموسيقى وجمع الأخبار.

لا يمكن أن تكون التكنولوجيا أكثر تأثيرًا من ذلك.

وكما قال المدون "فيل إدهولم"، "من المحتمل أن تتيح WebRTC وHTML5 إمكانية إجراء التحويل نفسه على الاتصالات في الوقت الفعلي الذي أتاحته المتصفحات الأصلية للمعلومات".

أدوات المطوّرين

مزيد من المعلومات

المعايير والبروتوكولات

ملخّص حول التوافق مع WebRTC

واجهات برمجة التطبيقات MediaStream وgetUserMedia

  • الإصدار 18.0.1008 من متصفّح Chrome للكمبيوتر المكتبي والإصدارات الأحدث، والإصدار 29 من متصفّح Chrome لأجهزة Android والإصدارات الأحدث
  • ‫Opera 18 والإصدارات الأحدث، وOpera لنظام التشغيل Android 20 والإصدارات الأحدث
  • ‫Opera 12 وOpera Mobile 12 (استنادًا إلى محرك Presto)
  • ‫Firefox 17 والإصدارات الأحدث
  • ‫Microsoft Edge 16 والإصدارات الأحدث
  • الإصدار 11.2 من Safari والإصدارات الأحدث على iOS، والإصدار 11.1 والإصدارات الأحدث على MacOS
  • الإصدار 11.8 من UC أو إصدار أحدث على أجهزة Android
  • ‫Samsung Internet 4 والإصدارات الأحدث

RTCPeerConnection واجهة برمجة التطبيقات

  • الإصدار 20 من Chrome للكمبيوتر المكتبي والإصدارات الأحدث، والإصدار 29 من Chrome لأجهزة Android والإصدارات الأحدث (بدون علامة)
  • ‫Opera 18 والإصدارات الأحدث (مفعّلة تلقائيًا)، و‫Opera for Android 20 والإصدارات الأحدث (مفعّلة تلقائيًا)
  • ‫Firefox 22 والإصدارات الأحدث (مفعَّل تلقائيًا)
  • ‫Microsoft Edge 16 والإصدارات الأحدث
  • الإصدار 11.2 من Safari والإصدارات الأحدث على iOS، والإصدار 11.1 والإصدارات الأحدث على MacOS
  • ‫Samsung Internet 4 والإصدارات الأحدث

RTCDataChannel واجهة برمجة التطبيقات

  • إصدار تجريبي في Chrome 25، ولكنّه أكثر ثباتًا (ويتوافق مع Firefox) في Chrome 26 والإصدارات الأحدث؛ Chrome لنظام التشغيل Android 29 والإصدارات الأحدث
  • الإصدار الثابت (والذي يتوافق مع Firefox) في Opera 18 والإصدارات الأحدث، وOpera for Android 20 والإصدارات الأحدث
  • ‫Firefox 22 والإصدارات الأحدث (مفعَّل تلقائيًا)

لمزيد من المعلومات التفصيلية حول التوافق مع الأنظمة الأساسية المختلفة لواجهات برمجة التطبيقات، مثل getUserMedia وRTCPeerConnection، يُرجى الاطّلاع على caniuse.com وحالة النظام الأساسي Chrome.

تتوفّر أيضًا واجهات برمجة تطبيقات أصلية لـ RTCPeerConnection في المستندات على webrtc.org.