1. 准备工作
CameraStream
特征属于能够将视频信息流流式传输到智能显示屏、Chromecast 设备和智能手机的设备。CameraStream
trait 现在支持 WebRTC 协议,这意味着您可以大幅缩短从摄像头设备到 Google Nest 显示设备的启动和流式传输延迟时间。
前提条件
- 查看云到云入门指南。
学习内容
- 如何部署智能家居云服务。
- 如何将服务关联到 Google 助理。
- 如何使用 WebRTC 协议流式传输到 Google Nest 显示设备。
所需条件
- 网络浏览器,例如 Google Chrome。
- 安装了 Google Home 应用的 iOS 或 Android 设备。
- Node.js 10.16 或更高版本。
- 适用于 Firebase 的 Blaze(随用随付)方案。
- 支持全高清分辨率的内置或外置摄像头设备。
- 一部 Google Nest 显示设备。
2. 开始
安装 Firebase CLI
借助 Firebase CLI,您可以在本地提供 Web 应用并将其部署到 Firebase Hosting。
如需安装 Firebase CLI,请按以下步骤操作:
- 在您的终端中,下载并安装 Firebase CLI:
$ npm install -g firebase-tools
- 验证 CLI 是否已正确安装:
$ firebase --version
- 使用您的 Google 账号授权 Firebase CLI:
$ firebase login
创建和配置 Actions 项目
- 前往 Actions 控制台,然后点击 New project(新建项目)。
- 在项目名称文本框中,输入项目名称,然后点击创建项目。
- 在 What kind of Action do you want to build? 页面上,点击 Smart home >开始构建。该项目会在 Actions 控制台中打开。
- 点击开发 >调用。
- 在显示名称文本框中,输入操作名称,然后点击 Save。之后,当有要设置的设备时,此名称就会显示在 Google Home 应用中。对于此 Codelab,我们输入了
WebRTC Codelab
作为显示名称,但您也可以使用其他名称。
- 点击操作。
- 在 Fulfillment 网址 文本框中,输入占位符网址,例如
https://example.com
。
运行 CameraStream 客户端应用
此 Codelab 的源代码包含一个 WebRTC 客户端,该客户端可在摄像头与 Google 智能家居显示设备之间建立、协商和管理 WebRTC 会话。
如需运行 CameraStream WebRTC 客户端应用,请执行以下操作之一:
- 点击以下按钮将源代码下载到开发机器:
- 克隆以下 GitHub 代码库:
$ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git
该代码包含以下目录:
camerastream-start
目录,其中包含您在构建应用时所依据的起始代码。camerastream-done
目录,其中包含完成后的 Codelab 的解决方案代码。
camerastream-start
目录包含以下子目录:
public
子目录,其中包含可轻松控制和监控摄像头设备状态的前端界面。functions
子目录,其中包含一个完全实现的云服务,可通过 Cloud Functions for Firebase 和 Realtime Database 来管理相机。
起始代码包含 TODO
注释,用于指示您需要在什么位置添加或更改代码,如以下示例所示:
// TODO: Implement full SYNC response.
连接到 Firebase
- 前往
camerastream-start
目录,然后使用您的 Actions 项目设置 Firebase CLI:
$ cd camerastream-start $ firebase use PROJECT_ID
- 在
camerastream-start
目录中,找到functions
文件夹,然后安装所有必要的依赖项:
$ cd functions $ npm install
- 如果您看到以下消息,请忽略它。此警告是由旧版依赖项引起的。如需了解详情,请参阅此 GitHub 问题。
found 5 high severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
- 初始化 Firebase 项目:
$ firebase init
- 选择 Functions(函数)和 Hosting(托管)。这会初始化项目所需的 API 和功能。
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. ❯◯ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ◯ Firestore: Deploy rules and create indexes for Firestore ◉ Functions: Configure a Cloud Functions directory and its files ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ◯ Hosting: Set up GitHub Action deploys ◯ Storage: Configure a security rules file for Cloud Storage ◯ Extensions: Set up an empty Extensions manifest
- 使用默认文件配置 Cloud Functions 函数,并确保不会覆盖项目示例中的现有
index.js
和package.json
文件:
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite ? What language would you like to use to write Cloud Functions? JavaScript ? File functions/package.json already exists. Overwrite? No ? File functions/index.js already exists. Overwrite? No ? Do you want to install dependencies with npm now? Yes
- 使用项目代码中的
public
目录配置 Hosting,并使用现有的index.html
文件:
? What do you want to use as your public directory? public ? Configure as a single-page app (rewrite all urls to /index.html)? Yes ? Set up automatic builds and deploys with GitHub? No ? File public/index.html already exists. Overwrite? No
3. 交换会话描述协议 (SDP) 消息
SDP 消息的交换是建立 WebRTC 流的一个重要步骤。SDP 是一种基于文本的协议,用于描述多媒体会话的特征。它在 WebRTC 中用于协商点对点连接的参数,例如使用的编解码器、参与者的 IP 地址和用于媒体传输的端口。
如需以主机的身份使用 Realtime Database 在您的摄像头和智能家居 CameraStream 客户端应用之间交换 SDP 消息,请按以下步骤操作:
- 在 Firebase 控制台中,点击构建 >实时数据库 >创建数据库。
- 在“Realtime Database 位置”下拉菜单中,选择要托管数据库的适当位置。
- 选择以测试模式开始,然后点击启用。启用 Realtime Database 后,您需要能够从 CameraStream 客户端应用引用它。
- 在 Firebase 控制台中,选择 项目设置 >项目设置 >将 Firebase 添加到您的 Web 应用以启动设置工作流。
- 如果您已向 Firebase 项目添加了应用,请点击添加应用以显示平台选项。
- 输入应用的别名,例如
My web app
,然后点击 Register app。 - 在添加 Firebase SDK 部分中,选择使用 <script>代码。
- 复制
firebasebaseConfig
对象中的值,然后将其粘贴到camaerastream-start/public/webrtc_generator.js
文件中。
const firebaseConfig = {
apiKey: "XXXXX",
authDomain: "XXXXX",
projectId: "XXXXX",
storageBucket: "XXXXX",
messagingSenderId: "XXXXX",
appId: "XXXXX",
measurementId: "XXXXX"
};
- 点击继续前往控制台以完成此流程。您可以在项目设置页面上看到新创建的 Web 应用。
4. 创建 WebRTC 摄像头
现在,您已配置 Action,您的云服务需要处理以下 intent:
- 当 Google 助理想要了解用户连接了哪些设备时发生的
SYNC
intent。当用户关联账号时,系统会向您的服务发送此 intent。您应在响应时提供用户设备及其功能的 JSON 载荷。 - 当 Google 助理想要代表用户控制设备时发生的
EXECUTE/QUERY
intent。您应该在响应时提供 JSON 载荷,其中包含所请求的每台设备的执行状态。
在本部分中,您将更新之前部署的用于处理这些 intent 的函数。
更新 SYNC
响应
- 前往
functions/index.js
文件。它包含响应来自 Google 助理的请求的代码。 - 修改
SYNC
intent 以返回设备的元数据和功能:
index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: USER_ID,
devices: [{
id: 'camera',
type: 'action.devices.types.CAMERA',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.CameraStream',
],
name: {
defaultNames: ['My WebRTC Camera],
name: 'Camera',
nicknames: ['Camera'],
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-camera',
hwVersion: '1.0',
swVersion: '1.0.1',
},
willReportState: false,
attributes: {
cameraStreamSupportedProtocols:['webrtc'],
cameraStreamNeedAuthToken: true,
cameraStreamSupportsPreview: true
},
}],
},
};
});
处理 EXECUTE
intent
EXECUTE
intent 可处理用于更新设备状态的命令。响应会返回每个命令的状态(例如 SUCCESS
、ERROR
或 PENDING
)以及新的设备状态。
- 如需处理
EXECUTE
intent,请修改EXECUTE
intent,在functions/index.js
文件中返回 Firebase 项目的signaling
端点:
index.js
app.onExecute(async (body,headers) => {
var array = headers.authorization.split(' ');
var snapshot = await firebaseRef.ref('/userId/'+array[1]).once('value');
var offerGenLocation = snapshot.val().type;
const {requestId} = body;
var result = {
status: 'SUCCESS',
states: {
cameraStreamProtocol: 'webrtc',
cameraStreamSignalingUrl:'https://us-central1-<project-id>.cloudfunctions.net/signaling?token='+array[1], // TODO: Add Firebase hosting URL
cameraStreamIceServers: '',
cameraStreamOffer:'',
cameraStreamAuthToken:'',
},
ids: [
'camera'
],
};
return {
requestId: requestId,
payload: {
commands: [result],
},
};
处理跨源资源共享 (CORS)
- 如需处理因使用
POST
方法发送 SDP 而导致的 CORS,请将 Firebase Hosting 网址添加到functions/index.js
文件中的allowlist
数组:
index.js
'use strict';
const functions = require('firebase-functions');
const {smarthome} = require('actions-on-google');
const {google} = require('googleapis');
const util = require('util');
const admin = require('firebase-admin');
var allowList = ['https:www.gstatic.com','https://<project-id>.web.app']; //TODO Add Firebase hosting URL.
如需详细了解 CORS,请参阅跨域资源共享 (CORS)。
处理数据流终止
- 如需处理 WebRTC 数据流终止,请添加 Firebase“信号”函数网址添加到
public/webrtc_generator.js
文件中:
webrtc_generator.js
terminateButton.onclick = function(){
console.log('Terminating Stream!!')
var signalingURL = 'https://us-central1-<project-id>.cloudfunctions.net/signaling'; //TODO Add Firebase hosting URL
var http = new XMLHttpRequest();
部署到 Firebase
- 如需部署到 Firebase,请使用 Firebase CLI 部署更新后的云执行方式:
$ firebase deploy
此命令会部署一个 Web 应用和多个 Cloud Functions for Firebase:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
启用账号关联
如需在部署项目后启用账号关联,请按以下步骤操作:
- 在 Actions 控制台中,选择 Develop >账号关联。
- 在 OAuth 客户端信息部分的对应文本框中输入以下信息:
Client-ID |
|
客户端密钥 |
|
授权网址 |
|
令牌网址 |
|
- 点击保存 >测试。
5. 测试虚拟 WebRTC 摄像头
- 前往您在部署 Firebase 项目时看到的 Hosting 网址。您将看到以下界面,即 CameraStream 客户端应用:
- 在本地视频分辨率面板中,选择所需的视频。
- 向 CameraStream 客户端应用授予访问摄像头和麦克风的权限。客户端上会显示网络摄像头的视频画面。
关联到智能家居 CameraStream
操作
- 在 Google Home 应用中,点按添加 >与 Google 服务兼容。
- 搜索你创建的 Action,然后选择该 Action。
- 请记下这个由 5 个字符组成的具有唯一性的字母数字代码,因为您稍后需要用到。
- 点按返回。WebRTC 摄像头会添加到 Google Home 应用中的结构体。
启动 WebRTC 流
- 在 CameraStream 客户端应用的网页上,在账号关联令牌值文本框中输入上一部分中的字母数字代码,然后点击提交。
- 如需从 Google 智能显示屏设备启动 WebRTC 会话,请执行以下操作之一:
- 说“Hey Google,流式传输 WebRTC 摄像头”。
- 在 Google 智能显示屏设备上,依次点按家居控制 >相机 >WebRTC 摄像头。
在 Google 智能家居 CameraStream 客户端应用中,您会看到“Offer SPD and Answer SDP”(优惠 SPD 和 Answer SDP)已成功生成并交换。通过 WebRTC 将摄像头中的图片流式传输到 Google 智能显示屏设备。
6. 恭喜
恭喜!您已了解如何使用 WebRTC 协议从摄像头流式传输到 Google Nest 显示设备。