1. 始める前に
CameraStream
トレイトは、スマートディスプレイ、Chromecast デバイス、スマートフォンに動画フィードをストリーミングできるデバイスに使用します。WebRTC プロトコルが CameraStream
トレイト内でサポートされるようになりました。これにより、起動やカメラデバイスから Google Nest ディスプレイ デバイスへのストリーミングのレイテンシを大幅に短縮できます。
前提条件
- クラウド間の入門ガイドを確認する。
学習内容
- スマートホーム クラウド サービスをデプロイする方法。
- サービスを Google アシスタントに接続する方法。
- WebRTC プロトコルを使用して Google Nest ディスプレイ デバイスにストリーミングする方法。
必要なもの
- ウェブブラウザ(Google Chrome など)
- Google Home アプリがインストールされている iOS デバイスまたは Android デバイス
- Node.js バージョン 10.16 以降。
- Firebase の Blaze(従量課金制)プラン。
- フル HD 解像度に対応した内蔵または外付けのウェブカメラ デバイス。
- Google Nest ディスプレイ デバイス。
2. 始める
Firebase CLI をインストールする
Firebase CLI を使用すると、ウェブアプリをローカルで提供し、Firebase Hosting にデプロイできます。
Firebase CLI をインストールする手順は次のとおりです。
- ターミナルで、Firebase CLI をダウンロードしてインストールします。
$ npm install -g firebase-tools
- CLI が正しくインストールされていることを確認します。
$ firebase --version
- Google アカウントで Firebase CLI を承認します。
$ firebase login
Actions プロジェクトを作成して構成する
- Actions Console に移動し、[New project] をクリックします。
- [プロジェクト名] テキスト ボックスにプロジェクトの名前を入力し、[プロジェクトを作成] をクリックします。
- [What kind of Action do you want to build?] ページで、[Smart home] をクリックします >作成を開始する。Actions Console でプロジェクトが開きます。
- [開発] >呼び出し。
- [Display name] テキスト ボックスにアクションの名前を入力し、[Save] をクリックします。この名前は、後でセットアップするデバイスがあるときに Google Home アプリに表示されます。この Codelab では、表示名として「
WebRTC Codelab
」と入力していますが、別の名前を使用することもできます。
- [操作] をクリックします。
- [フルフィルメント URL] テキスト ボックスに、プレースホルダ URL(
https://example.com
など)を入力します。
CameraStream クライアント アプリを実行する
この Codelab のソースコードには、ウェブカメラと Google スマートホーム ディスプレイ デバイス間の WebRTC セッションを確立、ネゴシエート、管理する WebRTC クライアントが含まれています。
CameraStream WebRTC クライアント アプリを実行するには、次のいずれかを行います。
- 次のボタンをクリックして、開発マシンにソースコードをダウンロードします。
- この GitHub リポジトリのクローンを作成します。
$ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git
コードには次のディレクトリが含まれています。
camerastream-start
ディレクトリ。ビルドのベースとなるスターター コードが含まれます。camerastream-done
ディレクトリには、完成した Codelab の解答コードが含まれています。
camerastream-start
ディレクトリには、次のサブディレクトリがあります。
public
サブディレクトリ。カメラデバイスの状態を簡単に制御、モニタリングするためのフロントエンド UI が含まれています。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. Exchange Session Description Protocol(SDP)メッセージ
SDP メッセージの交換は、WebRTC ストリームの確立における重要なステップです。SDP は、マルチメディア セッションの特性を記述するテキストベースのプロトコルです。WebRTC では、使用するコーデック、参加者の IP アドレス、メディア トランスポートに使用されるポートなど、ピアツーピア接続のパラメータのネゴシエーションに使用されます。
Realtime Database をホストとして使用して、ウェブカメラとスマートホームの CameraStream クライアント アプリの間で SDP メッセージを交換する手順は次のとおりです。
- Firebase コンソールで [ビルド >Realtime Database >データベースを作成する。
- [Realtime Database のロケーション] プルダウン メニューで、データベースをホストする適切なロケーションを選択します。
- [テストモードで開始] を選択し、[有効にする] をクリックします。Realtime Database が有効になっている場合は、CameraStream クライアント アプリから参照できる必要があります。
- Firebase コンソールで、 [プロジェクト設定 >プロジェクト設定 >Firebase をウェブアプリに追加して、設定ワークフローを起動します。
- すでに Firebase プロジェクトにアプリを追加している場合は、[アプリを追加] をクリックするとプラットフォームのオプションが表示されます。
- アプリのニックネーム(
My web 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"
};
- [コンソールに進む] をクリックして手順を完了します。[プロジェクトの設定] ページに、新しく作成したウェブアプリが表示されます。
4. WebRTC カメラを作成する
アクションの構成が完了したので、クラウド サービスで次のインテントを処理する必要があります。
SYNC
インテントは、ユーザーが接続しているデバイスをアシスタントが問い合わせたときに発生します。これは、ユーザーがアカウントをリンクしたときにサービスに送信されます。ユーザーのデバイスとその機能の JSON ペイロードで応答する必要があります。EXECUTE/QUERY
インテントは、アシスタントがユーザーに代わってデバイスを操作しようとしたときに発生します。リクエストされた各デバイスの実行状態を格納した JSON ペイロードで応答する必要があります。
このセクションでは、これらのインテントを処理するために以前にデプロイした関数を更新します。
SYNC
レスポンスを更新する
functions/index.js
ファイルに移動します。これには、アシスタントからのリクエストに応答するコードが含まれています。SYNC
インテントを編集して、デバイスのメタデータと機能を返します。
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
インテントを処理する
EXECUTE
インテントは、デバイスの状態を更新するコマンドを処理します。レスポンスが返すのは、各コマンドのステータス(SUCCESS
、ERROR
、PENDING
など)と更新後のデバイスの状態です。
EXECUTE
インテントを処理するには、functions/index.js
ファイルで Firebase プロジェクトのsignaling
エンドポイントを返すようにEXECUTE
インテントを編集します。
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 URL を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 の「シグナル」関数の URL を
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
このコマンドは、ウェブアプリと複数の 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 Console で、[Develop] > [Develop] を選択します。アカウントのリンク。
- [OAuth クライアント情報] セクションで、対応するテキスト ボックスに次の情報を入力します。
Client-ID |
|
クライアント シークレット |
|
認可 URL |
|
トークンの URL |
|
- [保存 >テストをご覧ください。
5. 仮想 WebRTC カメラをテストする
- Firebase プロジェクトをデプロイしたときに表示された Hosting URL に移動します。次のインターフェース(CameraStream クライアント アプリ)が表示されます。
- [Local Video Resolution] パネルで、目的の動画を選択します。
- CameraStream クライアント アプリに、ウェブカメラとマイクへのアクセスを許可します。クライアントには、ウェブカメラからの動画フィードが表示されます。
スマートホームの CameraStream
アクションへのリンク
- Google Home アプリで [追加 >Works with Google。
- 作成したアクションを検索して選択します。
- 後で必要になるため、一意の 5 文字の英数字コードをメモしておきます。
- [元に戻す] をタップします。Google Home アプリでストラクチャに WebRTC カメラが追加されます。
WebRTC ストリームを開始する
- CameraStream クライアント アプリのウェブページで、[Account linking token value] テキスト ボックスの最後のセクションの英数字コードを入力し、[Submit] をクリックします。
- Google スマートディスプレイ デバイスから WebRTC セッションを開始するには、次のいずれかを行います。
- 「OK Google, WebRTC カメラをストリーミングして」と話しかけます。
- Google スマートディスプレイ デバイスで、[スマートホーム] >カメラ >WebRTC カメラ。
Google のスマートホームの CameraStream クライアント アプリから、Offer SPD と Answer SDP が正常に生成、交換されていることがわかります。ウェブカメラからの画像が WebRTC を使用して Google スマートディスプレイ デバイスにストリーミングされます。
6. 完了
これで、WebRTC プロトコルを使用してウェブカメラから Google Nest ディスプレイ デバイスにストリーミングする方法を学習しました。
その他の情報
- スマートホーム デバイスのトレイト
- Actions on Google: Node.js を使用したスマートホームのサンプル
- スマートホーム アクションのテストと共有