درس تطبيقي حول Firebase + WebRTC

1. مقدمة

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

ما ستتعرَّف عليه

  • بدء مكالمة فيديو في تطبيق ويب باستخدام WebRTC
  • الإشارة إلى الطرف البعيد باستخدام Cloud Firestore

المتطلبات

قبل بدء هذا الدرس التطبيقي حول الترميز، يُرجى التأكّد من إجراء ما يلي:

  • npm الذي يأتي عادةً مع Node.js - يُوصى بإضافة Node LTS

2- إنشاء مشروع Firebase وإعداده

إنشاء مشروع على Firebase

  1. في وحدة تحكُّم Firebase، انقر على "إضافة مشروع"، ثم اختَر اسم مشروع FirebaseRTC.

تذكّر رقم تعريف المشروع لمشروعك على Firebase.

  1. انقر على "إنشاء مشروع".

التطبيق الذي ستنشئه يستخدم خدمتين من خدمات Firebase المتاحة على الويب:

  • Cloud Firestore لحفظ البيانات المنظَّمة في السحابة الإلكترونية والحصول على إشعار فوري عند تحديث البيانات
  • Firebase Hosting لاستضافة مواد العرض الثابتة وعرضها

بالنسبة إلى هذا الدرس التطبيقي المحدّد، يمكنك إعداد "استضافة Firebase" من قبل في المشروع الذي ستنسخه. ومع ذلك، بالنسبة إلى Cloud Firestore، سنرشدك إلى خطوات ضبط واستخدام الخدمات باستخدام وحدة تحكم Firebase.

تفعيل Cloud Firestore

يستخدم التطبيق Cloud Firestore لحفظ رسائل المحادثة وتلقّي رسائل محادثة جديدة.

سيلزمك تفعيل Cloud Firestore:

  1. في قسم التطوير ضمن قائمة وحدة تحكم Firebase، انقر على قاعدة البيانات.
  2. انقر على إنشاء قاعدة بيانات في لوحة Cloud Firestore.
  3. اختر بدء وضع الاختبار، ثم انقر على "تفعيل" بعد قراءة بيان إخلاء المسؤولية حول قواعد الأمان.

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

3. الحصول على نموذج الرمز

إنشاء نسخة طبق الأصل من مستودع GitHub من سطر الأوامر:

git clone https://github.com/webrtc/FirebaseRTC

من المفترض أن يتم نسخ نموذج الرمز إلى الدليل FirebaseRTC. تأكد من تشغيل سطر الأوامر من هذا الدليل من الآن فصاعدًا:

cd FirebaseRTC

استيراد تطبيق البدء

افتح الملفات في FirebaseRTC في المُحرِّر وعدِّلها وفقًا للتعليمات الواردة أدناه. يحتوي هذا الدليل على رمز البداية لدرس الترميز الذي يتكون من تطبيق WebRTC لا يعمل بعد. سنفعّل هذه الميزة في هذا الدرس التطبيقي حول الترميز.

4- تثبيت واجهة سطر الأوامر في Firebase

تسمح لك واجهة سطر الأوامر في Firebase (CLI) بعرض تطبيق الويب محليًا ونشر تطبيق الويب في Firebase Hosting.

  1. ثبِّت سطر الأوامر من خلال تنفيذ الأمر npm التالي: sh npm -g install firebase-tools
  1. تأكَّد من تثبيت سطر الأوامر (CLI) بشكل صحيح من خلال تنفيذ الأمر التالي: sh firebase --version

تأكَّد من أن إصدار Firebase CLI هو الإصدار 6.7.1 أو إصدار أحدث.

  1. عليك تفويض واجهة سطر الأوامر (CLI) في Firebase عن طريق تنفيذ الأمر التالي: sh firebase login

لقد أعددت نموذج تطبيق الويب لسحب إعداد تطبيقك إلى Firebase الاستضافة من الملفات والملفات المحلية في تطبيقك. ولإجراء ذلك، عليك ربط تطبيقك بمشروع Firebase.

  1. اربط تطبيقك بمشروع Firebase من خلال تنفيذ الأمر التالي: sh firebase use --add

  2. اختَر رقم تعريف المشروع عندما يُطلب منك ذلك، ثم امنح مشروعك على Firebase اسمًا مستعارًا.

ويكون الاسم المستعار مفيدًا إذا كانت لديك بيئات متعددة (الإنتاج أو التجهيز، وما إلى ذلك). ومع ذلك، في هذا الدرس التطبيقي حول الترميز، ما عليك سوى استخدام الاسم المستعار لـ default.

  1. اتّبِع التعليمات المتبقية في سطر الأوامر.

5. تشغيل الخادم المحلي

أنت على استعداد لبدء العمل على تطبيقنا. لنشغِّل التطبيق محليًا.

  1. شغِّل الأمر التالي CLI في Firebase: sh firebase serve --only hosting

  2. يجب أن يعرض سطر الأوامر الرد التالي: hosting: Local server: http://localhost:5000

نستخدم محاكي استضافة Firebase لعرض تطبيقنا محليًا. من المفترض أن يكون تطبيق الويب متوفرًا الآن من http://localhost:5000.

  1. افتح التطبيق على http://localhost:5000.

من المفترض أن تظهر نسختك من FirebaseRTC التي تم ربطها بمشروعك في Firebase.

تم ربط التطبيق تلقائيًا بمشروع Firebase.

6. إنشاء غرفة جديدة

في هذا التطبيق، يُطلق على كل جلسة محادثة فيديو اسم غرفة. يمكن للمستخدم إنشاء غرفة جديدة من خلال النقر على زر في تطبيقه. سيؤدي ذلك إلى إنشاء رقم تعريف يمكن للجهة البعيدة استخدامه للانضمام إلى الغرفة نفسها. يتم استخدام المعرّف كمفتاح في Cloud Firestore لكل غرفة.

ستحتوي كل غرفة على RTCSessionDescriptions لكل من العرض والإجابة، بالإضافة إلى مجموعتَين منفصلتَين لكل من الطرفين لعرض منتجات ICE.

وتتمثل مهمتك الأولى في تنفيذ الرمز المفقود لإنشاء غرفة جديدة العرض الأولي من المتصل. افتح public/app.js وابحث عن التعليق // Add code for creating a room here وأضف الرمز التالي:

const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

const roomWithOffer = {
    offer: {
        type: offer.type,
        sdp: offer.sdp
    }
}
const roomRef = await db.collection('rooms').add(roomWithOffer);
const roomId = roomRef.id;
document.querySelector('#currentRoom').innerText = `Current room is ${roomId} - You are the caller!`

ينشئ السطر الأول RTCSessionDescription الذي سيمثل العرض من المتصل. يتم بعد ذلك ضبط هذا الوصف كوصف محلي، وتتم كتابته أخيرًا في كائن الغرفة الجديد ضمن Cloud Firestore.

سنستمع بعد ذلك إلى التغييرات في قاعدة البيانات ونرصد الوقت الذي تمت فيه إضافة إجابة من المدعو.

roomRef.onSnapshot(async snapshot -> {
    console.log('Got updated room:', snapshot.data());
    const data = snapshot.data();
    if (!peerConnection.currentRemoteDescription && data.answer) {
        console.log('Set remote description: ', data.answer);
        const answer = new RTCSessionDescription(data.answer)
        await peerConnection.setRemoteDescription(answer);
    }
});

سينتظر هذا الإجراء إلى أن يكتب المتصل RTCSessionDescription للرد، ويضبطه كوصف عن بُعد على المتصل RTCPeerConnection.

7- الانضمام إلى غرفة

الخطوة التالية هي تطبيق المنطق للانضمام إلى غرفة حالية. يتم ذلك للمستخدم من خلال النقر على زر الانضمام إلى غرفة وإدخال رقم تعريف الغرفة للانضمام. مهمتك هنا هي تنفيذ إنشاء RTCSessionDescription للإجابة وتحديث الغرفة في قاعدة البيانات وفقًا لذلك.

const offer = roomSnapshot.data().offer;
await peerConnection.setRemoteDescription(offer);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);

const roomWithAnswer = {
    answer: {
        type: answer.type,
        sdp: answer.sdp
    }
}
await roomRef.update(roomWithAnswer);

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

8- جمع العناصر المرشحة لـ ICE

قبل أن يتمكن المتصل والمستخدم المتصل من الاتصال ببعضهما البعض، عليه أيضًا تبادل مرشحات ICE التي تخبر WebRTC بكيفية الاتصال بنظير بعيد. تتمثل مهمتك التالية في تنفيذ الرمز الذي يستمع إلى العناصر المرشحة لـ ICE ويضيفها إلى مجموعة في قاعدة البيانات. ابحَث عن الدالة collectIceCandidates وأضِف الرمز التالي:

async function collectIceCandidates(roomRef, peerConnection,
                                    localName, remoteName) {
    const candidatesCollection = roomRef.collection(localName);

    peerConnection.addEventListener('icecandidate', event -> {
        if (event.candidate) {
            const json = event.candidate.toJSON();
            candidatesCollection.add(json);
        }
    });

    roomRef.collection(remoteName).onSnapshot(snapshot -> {
        snapshot.docChanges().forEach(change -> {
            if (change.type === "added") {
                const candidate = new RTCIceCandidate(change.doc.data());
                peerConneciton.addIceCandidate(candidate);
            }
        });
    })
}

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

9- الخاتمة

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

لمزيد من المعلومات، انتقِل إلى المراجع التالية:

  1. رمز مصدر FirebaseRTC
  2. نماذج WebRTC
  3. Cloud Firestore