1. 始める前に
CameraStream トレイトは、スマート ディスプレイ、Chromecast デバイス、スマートフォンに動画フィードをストリーミングする機能を搭載したデバイスに使用します。CameraStream トレイト内で WebRTC プロトコルがサポートされるようになりました。これにより、カメラ デバイスから 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
プロジェクトを作成する
- Google Home Developer Console に移動します。
- [プロジェクトを作成] をクリックし、プロジェクトの名前を入力して [プロジェクトを作成] をクリックします。

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.
Google Home Developer Console プロジェクトに Firebase を追加する
方法 1: Firebase コンソールを使用する
- Firebase に移動します。
- [Firebase プロジェクトを作成する] をクリックします。

- [プロジェクトを作成] 画面で、[Google Cloud プロジェクトに Firebase を追加] をクリックします。

- [スタートガイド] 画面で、Google Home Developer Console で作成した Google Cloud プロジェクトを選択し、[続行] をクリックします。

方法 2: Firebase CLI を使用する
firebase projects:addfirebase
作成したばかりの Google Home Developer Console プロジェクトを選択して、Firebase を追加します。
Firebase が Google Home Developer Console プロジェクトに追加されると、Firebase コンソールに表示されます。Firebase プロジェクトのプロジェクト ID は、Google Home Developer Console のプロジェクト ID と一致します。

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 features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed) >( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore ( ) Genkit: Setup a new Genkit project with Firebase (*) Functions: Configure a Cloud Functions directory and its files ( ) App Hosting: Configure an apphosting.yaml file for App Hosting (*) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ( ) Storage: Configure a security rules file for Cloud Storage ( ) Emulators: Set up local emulators for Firebase products ( ) Remote Config: Configure a template file for Remote Config ( ) Extensions: Set up an empty Extensions manifest (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore
- デフォルト ファイルを使用して 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ディレクトリと既存のindex.htmlファイルが使用されるように Hosting を構成します。
? 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 のロケーション] プルダウン メニューで、データベースをホストする適切なロケーションを選択します。
![[データベースを設定] ダイアログの [Realtime Database のロケーション] プルダウン メニュー](https://developers.home.google.com/static/codelabs/smarthome-webrtc/img/121bb05a2812c639.png?authuser=2&hl=ja)
- [テストモードで開始] を選択し、[有効にする] をクリックします。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
},
}],
},
};
});
USER_IDがコードで定義されていません。const _ = require('underscore');の下に以下を追加します。
// Hardcoded user ID
const USER_ID = '123';
EXECUTE インテントを処理する
EXECUTE インテントは、デバイスの状態を更新するコマンドを処理します。レスポンスが返すのは、各コマンドのステータス(SUCCESS、ERROR、PENDING など)と更新後のデバイスの状態です。
EXECUTE インテントを処理するには、EXECUTE インテントを編集して、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 を処理するには、functions/index.js ファイルの allowlist 配列に Firebase Hosting の URL を追加します。
index.js
'use strict';
.....
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
Developer Console プロジェクトを構成する
- デベロッパー コンソールに移動します。
- [プロジェクトを作成] をクリックし、プロジェクトの名前を入力して [プロジェクトを作成] をクリックします。

クラウド間統合を選択する
デベロッパー コンソールの [プロジェクト ホーム] で、[Cloud-to-cloud] の [Add cloud-to-cloud integration] を選択します。

- [統合名] を入力し、[デバイスタイプ] で [カメラ] を選択します。この名前は、後で Google Home アプリに表示されます。この Codelab では、表示名として「WebRTC Codelab」と入力しましたが、別の名前を使用することもできます。

- [アプリのブランディング] で、144×144 ピクセルのサイズで
という名前のアプリ アイコンの.png pngファイルをアップロードします。

アカウント リンクを有効にする
プロジェクトのデプロイ後にアカウント リンクを有効にする手順は次のとおりです。
- デベロッパー コンソールに移動して、プロジェクトを開きます。
- [Cloud-to-Cloud] セクションで、インテグレーションの横にある [開発] > [編集] をクリックします。
- [設定と構成] ページで、[アカウントのリンク] セクションを見つけ、対応するテキスト ボックスに次の情報を入力します。
クライアント ID |
|
クライアント シークレット |
|
認証 URL |
|
トークンの URL |
|

- [保存] > [テスト] をクリックします。
5. 仮想 WebRTC カメラをテストする
- Firebase プロジェクトをデプロイしたときに表示された Hosting URL に移動します。次のインターフェース(CameraStream クライアント アプリ)が表示されます。

- [ローカル動画の解像度] パネルで、目的の動画を選択します。
- CameraStream クライアント アプリにウェブカメラとマイクへのアクセスを許可します。ウェブカメラからの動画フィードがクライアントに表示されます。
スマートホーム CameraStream アクションにリンクする
- Google Home アプリで、[追加] > [Google と連携させる] をタップします。
![Google Home アプリの [デバイスのセットアップ] ページ](https://developers.home.google.com/static/codelabs/smarthome-webrtc/img/51f56113f915f2c0.png?authuser=2&hl=ja)
- 作成したアクションを検索して選択します。

- 後で必要になるため、5 文字の英数字の固有コードをメモしておきます。

- [元に戻す] をタップします。WebRTC カメラが Google Home アプリのストラクチャに追加されます。
WebRTC ストリームを開始する
- CameraStream クライアント アプリのウェブページで、最後のセクションの英数字コードを [Account linking token value] テキスト ボックスに入力し、[Submit] をクリックします。
テキスト ボックス](https://developers.home.google.com/static/codelabs/smarthome-webrtc/img/61b611d8ae35224b.png?authuser=2&hl=ja)
- Google スマート ディスプレイ デバイスから WebRTC セッションを開始するには、次のいずれかを行います。
- 「OK Google, WebRTC カメラをストリーミングして」と話しかけます。
- Google スマート ディスプレイで、[ホーム コントロール] > [カメラ] > [WebRTC カメラ] をタップします。
Google スマートホームの CameraStream クライアント アプリで、Offer SPD と Answer SDP が正常に生成され、交換されたことを確認します。ウェブカメラの画像は、WebRTC を使用して Google スマートディスプレイ デバイスにストリーミングされます。
6. 完了
おめでとうございます!WebRTC プロトコルを使用してウェブカメラから Google Nest ディスプレイ デバイスにストリーミングする方法を学習しました。
その他の情報
- スマートホーム デバイスのトレイト
- Actions on Google: Node.js を使用したスマートホームのサンプル
- スマートホーム アクションのテストと共有