Lớp học lập trình về Firebase và WebRTC

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách xây dựng một ứng dụng trò chuyện video đơn giản bằng cách sử dụng API WebRTC trong trình duyệt và Cloud Firestore để báo hiệu. Ứng dụng này có tên là FirebaseRTC và hoạt động như một ví dụ đơn giản sẽ hướng dẫn bạn những kiến thức cơ bản về cách tạo ứng dụng hỗ trợ WebRTC.

Kiến thức bạn sẽ học được

  • Bắt đầu cuộc gọi video trong một ứng dụng web bằng WebRTC
  • Báo hiệu cho nhóm ở xa bằng Cloud Firestore

Bạn cần có

Trước khi bắt đầu lớp học lập trình này, hãy đảm bảo rằng bạn đã cài đặt:

  • npm thường đi kèm với Node.js – Bạn nên dùng Node LTS

2. Tạo và thiết lập dự án Firebase

Tạo dự án Firebase

  1. Trong bảng điều khiển của Firebase, hãy nhấp vào Thêm dự án, sau đó đặt tên cho dự án Firebase Firebase.

Ghi nhớ Mã dự án cho dự án Firebase.

  1. Nhấp vào Tạo dự án.

Ứng dụng mà bạn sẽ tạo sử dụng hai dịch vụ Firebase có sẵn trên web:

  • Cloud Firestore để lưu dữ liệu có cấu trúc trên Đám mây và nhận thông báo tức thì khi dữ liệu được cập nhật
  • Lưu trữ Firebase để lưu trữ và phân phát các tài sản tĩnh của bạn

Đối với lớp học lập trình cụ thể này, bạn đã định cấu hình Dịch vụ lưu trữ Firebase trong dự án mà bạn sẽ sao chép. Tuy nhiên, đối với Cloud Firestore, chúng tôi sẽ hướng dẫn bạn cách định cấu hình và bật dịch vụ bằng bảng điều khiển của Firebase.

Bật Cloud Firestore

Ứng dụng sử dụng Cloud Firestore để lưu tin nhắn trò chuyện và nhận tin nhắn trò chuyện mới.

Bạn cần bật Cloud Firestore:

  1. Trong phần Phát triển trên bảng điều khiển của Firebase, hãy nhấp vào Cơ sở dữ liệu.
  2. Nhấp vào Tạo cơ sở dữ liệu trong ngăn Cloud Firestore.
  3. Chọn tùy chọn Bắt đầu ở chế độ thử nghiệm, sau đó nhấp vào Bật sau khi đọc tuyên bố từ chối trách nhiệm về quy tắc bảo mật.

Chế độ thử nghiệm đảm bảo rằng bạn có thể thoải mái ghi vào cơ sở dữ liệu trong quá trình phát triển. Chúng tôi sẽ làm cho cơ sở dữ liệu của mình an toàn hơn sau này trong lớp học lập trình này.

3. Lấy mã mẫu

Sao chép kho lưu trữ GitHub từ dòng lệnh:

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

Bạn phải sao chép mã mẫu vào thư mục FirebaseRTC. Đảm bảo dòng lệnh của bạn được chạy từ thư mục này kể từ bây giờ:

cd FirebaseRTC

Nhập ứng dụng dành cho người mới bắt đầu

Mở các tệp trong FirebaseRTC trong trình chỉnh sửa của bạn và thay đổi chúng theo hướng dẫn bên dưới. Thư mục này chứa mã bắt đầu cho lớp học lập trình bao gồm một ứng dụng WebRTC đầy đủ chức năng. Chúng tôi sẽ giúp lớp học này hoạt động trong toàn bộ lớp học lập trình này.

4. Cài đặt giao diện dòng lệnh Firebase

Giao diện dòng lệnh Firebase (CLI) cho phép bạn phân phát ứng dụng web tại địa phương và triển khai ứng dụng web tới dịch vụ Lưu trữ Firebase.

  1. Cài đặt CLI bằng cách chạy lệnh npm sau: sh npm -g install firebase-tools
  1. Xác minh rằng CLI đã được cài đặt chính xác bằng cách chạy lệnh sau: sh firebase --version

Đảm bảo phiên bản của CLI Firebase là phiên bản 6.7.1 trở lên.

  1. Ủy quyền cho CLI Firebase bằng cách chạy lệnh sau: sh firebase login

Bạn đã thiết lập mẫu ứng dụng web để lấy cấu hình của ứng dụng cho Firebase Lưu trữ từ thư mục cục bộ và tệp của ứng dụng. Nhưng để làm điều này, bạn cần liên kết ứng dụng của mình với dự án Firebase.

  1. Liên kết ứng dụng của bạn với dự án Firebase bằng cách chạy lệnh sau: sh firebase use --add

  2. Khi được nhắc, hãy chọn Mã dự án, sau đó đặt bí danh cho dự án Firebase.

Bí danh sẽ hữu ích nếu bạn có nhiều môi trường (hoạt động sản xuất, thử nghiệm, v.v.). Tuy nhiên, trong lớp học lập trình này, hãy dùng bí danh của default.

  1. Làm theo các hướng dẫn còn lại trong dòng lệnh.

5. Chạy máy chủ cục bộ

Bạn đã sẵn sàng bắt đầu công việc trên ứng dụng của chúng tôi! Hãy chạy ứng dụng trên máy!

  1. Chạy lệnh CLI Firebase sau: sh firebase serve --only hosting

  2. Dòng lệnh sẽ hiển thị phản hồi sau đây: hosting: Local server: http://localhost:5000

Chúng tôi đang sử dụng trình mô phỏng Lưu trữ Firebase để phân phát ứng dụng tại địa phương. Ứng dụng web giờ đây sẽ có sẵn từ http://localhost:5000.

  1. Mở ứng dụng của bạn tại http://localhost:5000.

Bạn sẽ thấy bản sao của FirebaseRTC đã được kết nối với dự án Firebase của bạn.

Ứng dụng đã tự động kết nối với dự án Firebase của bạn.

6. Đang tạo phòng mới

Trong ứng dụng này, mỗi phiên trò chuyện video được gọi là một phòng. Người dùng có thể tạo phòng mới bằng cách nhấp vào nút trong ứng dụng của họ. Thao tác này sẽ tạo một mã mà bên thứ ba từ xa có thể dùng để tham gia cùng một phòng. Mã này được dùng làm khóa trong Cloud Firestore cho mỗi phòng.

Mỗi phòng sẽ chứa RTCSessionDescriptions cho cả ưu đãi và câu trả lời, cũng như hai bộ sưu tập riêng biệt có các ứng cử viên ICE từ mỗi bên.

Nhiệm vụ đầu tiên của bạn là triển khai mã bị thiếu để tạo phòng mới với ưu đãi ban đầu của người gọi. Mở public/app.js rồi tìm nhận xét // Add code for creating a room here rồi thêm mã sau:

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!`

Dòng đầu tiên tạo một RTCSessionDescription đại diện cho ưu đãi từ người gọi. Sau đó, đối tượng này được đặt làm nội dung mô tả cục bộ và cuối cùng được ghi vào đối tượng phòng mới trong Cloud Firestore.

Tiếp theo, chúng tôi sẽ lắng nghe những thay đổi đối với cơ sở dữ liệu và phát hiện thời điểm câu trả lời từ cuộc gọi được thêm vào.

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

Thao tác này sẽ chờ cho đến khi cuộc gọi ghi RTCSessionDescription câu trả lời và đặt nội dung đó làm nội dung mô tả từ xa trên người gọi RTCPeerConnection.

7. Tham gia phòng

Bước tiếp theo là triển khai logic để tham gia một phòng hiện có. Người dùng thực hiện việc này bằng cách nhấp vào nút Tham gia phòng rồi nhập mã nhận dạng cho phòng đó để tham gia. Nhiệm vụ của bạn ở đây là triển khai việc tạo RTCSessionDescription cho câu trả lời và cập nhật phòng trong cơ sở dữ liệu.

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

Trong đoạn mã ở trên, chúng tôi bắt đầu bằng cách trích xuất ưu đãi từ người gọi và tạo RTCSessionDescription mà chúng tôi đặt làm nội dung mô tả từ xa. Tiếp theo, chúng ta tạo câu trả lời, đặt câu trả lời làm nội dung mô tả cục bộ và cập nhật cơ sở dữ liệu. Bản cập nhật cơ sở dữ liệu sẽ kích hoạt lệnh gọi lại onSnapshot ở phía người gọi. Hành động này sẽ đặt mô tả từ xa dựa trên câu trả lời từ bên được gọi. Thao tác này sẽ hoàn tất việc trao đổi đối tượng RTCSessionDescription giữa trình gọi và phương thức gọi.

8. Tập hợp các ứng cử viên ICE

Trước khi người gọi và người được gọi có thể kết nối với nhau, họ cũng cần phải trao đổi các ứng viên ICE để thông báo cho WebRTC cách kết nối với ứng dụng ngang hàng từ xa. Nhiệm vụ tiếp theo của bạn là triển khai mã lắng nghe các ứng viên ICE và thêm chúng vào một bộ sưu tập trong cơ sở dữ liệu. Tìm hàm collectIceCandidates và thêm mã sau:

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());
                peerConnection.addIceCandidate(candidate);
            }
        });
    })
}

Hàm này thực hiện hai việc. Nền tảng này sẽ thu thập các ứng viên ICE từ API WebRTC và thêm họ vào cơ sở dữ liệu và lắng nghe các ứng viên ICE đã thêm từ ứng dụng ngang hàng từ xa và thêm họ vào bản sao RTCPeerConnection. Điều quan trọng là khi bạn phải lắng nghe những thay đổi đối với cơ sở dữ liệu để lọc bỏ những nội dung không phải là mới bổ sung, vì nếu không thì chúng tôi sẽ thêm cùng một nhóm ứng viên ICE nhiều lần.

9. Kết luận

Trong lớp học lập trình này, bạn đã học cách triển khai tín hiệu cho WebRTC bằng cách sử dụng Cloud Fi Khôi phục, cũng như cách sử dụng tính năng đó để tạo một ứng dụng trò chuyện video đơn giản.

Để tìm hiểu thêm, hãy truy cập vào các tài nguyên sau:

  1. Mã nguồn FirebaseRTC
  2. Mẫu WebRTC
  3. Cloud Firestore