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 tạo 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 để truyền tín hiệu. Chiến lược phát hành đĩa đơn được gọi là FirebaseRTC và hoạt động như một ví dụ đơn giản sẽ dạy cho bạn thông tin cơ bản về cách xây dựng ứng dụng hỗ trợ WebRTC.

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

  • Thực hiện cuộc gọi video trong ứng dụng web bằng WebRTC
  • Gửi tín hiệu đến bên từ 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 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 Firebase, sau đó đặt tên cho dự án Firebase là FirebaseRTC.

Ghi nhớ Mã dự án cho dự án Firebase của bạn.

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

Ứng dụng mà bạn sắp tạo dùng 2 dịch vụ Firebase có sẵn trên web:

  • Cloud Firestore giúp lưu dữ liệu có cấu trúc lên đám mây và hoạt động ngay lập tức thông báo 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 tính năng Lưu trữ Firebase trong 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ấ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 cuộc trò chuyện mới tin nhắn.

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

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

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

3. Nhận 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 từ bây giờ, dòng lệnh sẽ chạy từ thư mục này:

cd FirebaseRTC

Nhập ứng dụng khởi đầ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ã khởi đầu cho lớp học lập trình này bao gồm một ứng dụng WebRTC chưa hoạt động. Chúng tôi sẽ giúp bạn hoạt động trong suốt 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 (CLI) của Firebase cho phép bạn phân phát ứng dụng web của mình cục bộ và triển khai ứng dụng web của bạn đến 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 đúng cách bằng cách chạy lệnh sau : sh firebase --version

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

  1. Cho phép giao diện dòng lệnh (CLI) của 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ừ các tệp và thư mục cục bộ trong ứng dụng của bạn. Nhưng để làm được điều này, bạn cần liên kết ứng dụng với dự án Firebase của bạn.

  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 đây : sh firebase use --add

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

Bí danh sẽ hữu ích nếu bạn có nhiều môi trường (sản xuất, thử nghiệm, v.v.). Tuy nhiên, đối với lớp học lập trình này, hãy sử 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 làm việc trên ứng dụng của chúng tôi! Hãy chạy ứng dụng cục bộ!

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

  2. Dòng lệnh của bạn sẽ hiển thị phản hồi sau: 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 cục bộ. Ứng dụng web hiện 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 FirebaseRTC đã được kết nối với Dự án Firebase.

Ứng dụng này đã 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 một phòng mới bằng cách nhấp vào một nút trong ứng dụng của họ. Thao tác này sẽ tạo một mã nhận dạng mà nhóm từ xa có thể sử dụng để tham gia cùng một phòng. Mã nhận dạng được dùng làm khoá trong Cloud Firestore cho từng 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 với các ứng cử viên ICE của mỗi bên.

Nhiệm vụ đầu tiên của bạn là triển khai mã còn thiếu để tạo một phòng mới bằng lời đề nghị ban đầu từ 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 sẽ đại diện cho ưu đãi từ phương thức gọi. Thông tin này sau đó được đặt làm mô tả cục bộ và cuối cùng được viết vào đối tượng Room mới trong Cloud Firestore.

Tiếp theo, chúng ta sẽ theo dõi 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ừ đã được thêm phương thức gọi.

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ẽ đợi cho đến khi hàm được gọi viết RTCSessionDescription cho hàm trả lời và đặt làm nội dung mô tả từ xa cho phương thức gọi RTCPeerConnection

7. Tham gia một 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 của phòng tham gia. Nhiệm vụ của bạn ở đây là triển khai việc tạo RTCSessionDescription để có câu trả lời và cập nhật phòng trong cơ sở dữ liệu cho phù hợp.

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 mã trên, chúng ta bắt đầu bằng cách trích xuất phiếu mua hàng từ người gọi và tạo RTCSessionDescription mà chúng ta đặt làm mô tả từ xa. Tiếp theo, chúng tôi tạo câu trả lời, đặt 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ủa cơ sở dữ liệu sẽ kích hoạt lệnh gọi lại onSnapshot ở phía người gọi. Lệnh này sẽ thiết lập mô tả từ xa dựa trên câu trả lời của người được gọi. Thao tác này hoàn tất quá trình trao đổi các đối tượng RTCSessionDescription giữa phương thức gọi và người được gọi.

8. Thu thập các ứng 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, chúng cũng cần trao đổi các ứng viên ICE cho WebRTC biết 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 vào một tập hợ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 2 việc. Giao thức này thu thập các ứng viên ICE từ API WebRTC và thêm chúng vào cơ sở dữ liệu và theo dõi các đề xuất ICE được thêm từ điều khiển từ xa ngang hàng và thêm chúng vào thực thể RTCPeerConnection. Điều quan trọng là khi theo dõi các thay đổi trong cơ sở dữ liệu để lọc ra mọi nội dung không phải là nội dung bổ sung mới, vì lẽ ra chúng ta sẽ thêm cùng một nhóm ứng cử viên ICE nhiều lần một lần nữa.

9. Kết luận

Trong lớp học lập trình này, bạn đã tìm hiểu cách triển khai tín hiệu cho WebRTC bằng Cloud Firestore, cũng như cách sử dụng tính năng đó để tạo một cuộc 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