1. 简介
在此 Codelab 中,您将学习如何在浏览器中使用 WebRTC API 构建简单的视频聊天应用,并使用 Cloud Firestore 发出信号。该应用名为 FirebaseRTC,它通过一个简单的示例,向您展示了如何构建支持 WebRTC 的应用的基础知识。
学习内容
- 使用 WebRTC 在 Web 应用中发起视频通话
- 使用 Cloud Firestore 向远程方发送信号
您需要满足的条件
在开始此 Codelab 之前,请确保您已安装:
- npm(通常随 Node.js 一起提供)- 建议使用 Node LTS
2. 创建并设置 Firebase 项目
创建 Firebase 项目
- 在 Firebase 控制台中,点击“添加项目”,然后将 Firebase 项目命名为 FirebaseRTC。
记住您的 Firebase 项目的 ID。
- 点击“创建项目”。
您要构建的应用使用 Web 提供的两种 Firebase 服务:
- Cloud Firestore,用于在云端保存结构化数据,并在数据更新时立即获取通知
- Firebase Hosting,用于托管和提供您的静态资源
在此特定的 Codelab 中,您已在要克隆的项目中配置 Firebase Hosting。不过,对于 Cloud Firestore,我们将引导您使用 Firebase 控制台配置和启用这些服务。
启用 Cloud Firestore
该应用使用 Cloud Firestore 保存聊天消息和接收新的聊天消息。
您需要启用 Cloud Firestore:
- 在 Firebase 控制台的“开发”部分,点击“数据库”。
- 在 Cloud Firestore 窗格中点击创建数据库。
- 选择以测试模式开始选项,然后在阅读有关安全规则的免责声明后点击“启用”。
测试模式可确保您在开发过程中可以随意向数据库写入数据。此 Codelab 后面会介绍如何提升数据库的安全性。
3.获取示例代码
从命令行克隆 GitHub 代码库:
git clone https://github.com/webrtc/FirebaseRTC
示例代码应该克隆到 FirebaseRTC
目录中。从现在开始,请确保您的命令行从此目录运行:
cd FirebaseRTC
导入入门版应用
在编辑器中打开 FirebaseRTC
中的文件,然后按照下面的说明进行更改。此目录包含 Codelab 的起始代码,其中包含一个尚不起作用的 WebRTC 应用。我们将在此 Codelab 中使其正常运行。
4.安装 Firebase 命令行界面
借助 Firebase 命令行界面 (CLI),您可以在本地提供 Web 应用,并将您的 Web 应用部署到 Firebase Hosting。
- 通过运行以下 npm 命令安装 CLI:
sh npm -g install firebase-tools
- 运行以下命令,验证 CLI 是否已正确安装:
sh firebase --version
确保 Firebase CLI 版本为 v6.7.1 或更高版本。
- 通过运行以下命令向 Firebase CLI 授权:
sh firebase login
您已设置 Web 应用模板,以便从应用的本地目录和文件中提取应用的 Firebase Hosting 配置。但要执行此操作,您需要将应用与 Firebase 项目相关联。
运行以下命令,将您的应用与 Firebase 项目相关联:
sh firebase use --add
出现提示时,选择您的项目 ID,然后为您的 Firebase 项目指定一个别名。
如果您有多个环境(生产、预演等),别名会非常有用。不过,在此 Codelab 中,我们仅使用 default
的别名。
按照命令行中的其余说明操作。
5. 运行本地服务器
您可以开始使用我们的应用了!让我们在本地运行应用!
运行以下 Firebase CLI 命令:
sh firebase serve --only hosting
您的命令行应显示以下响应:
hosting: Local server: http://localhost:5000
我们使用 Firebase Hosting 模拟器在本地提供应用。Web 应用现在应该可从 http://localhost:5000 访问。
- 访问 http://localhost:5000 打开您的应用。
您应该会看到已关联至您的 Firebase 项目的 FirebaseRTC 副本。
该应用已自动连接到您的 Firebase 项目。
6. 创建新聊天室
在此应用中,每个视频聊天会话都称为一个聊天室。用户可以通过点击应用中的按钮来创建新的聊天室。这样将生成一个 ID,远程方可通过该 ID 加入同一个会议室。该 ID 用作每个房间在 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 中的新 Room 对象。
接下来,我们将监听数据库的更改,并检测何时添加了被调用方的答案。
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. 正在加入聊天室
下一步是实现加入现有聊天室的逻辑。用户可通过点击加入聊天室按钮并输入要加入的聊天室的 ID 来实现此目的。您的任务是实现为答案创建 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());
peerConnection.addIceCandidate(candidate);
}
});
})
}
此函数有两点用途。它会从 WebRTC API 收集 ICE 候选指令并将其添加到数据库中,并监听远程对等方中已添加的 ICE 候选指令,并将其添加到其 RTCPeerConnection
实例中。在监听数据库更改时,请务必过滤掉不是新添加的内容,否则我们必须反复添加同一组 ICE 候选对象。
9. 总结
在此 Codelab 中,您学习了如何使用 Cloud Firestore 为 WebRTC 实现信令机制,以及如何使用它来创建简单的视频聊天应用。
要了解详情,请访问以下资源: