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
プロジェクトを作成する
- 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.
Firebase プロジェクトを作成する
- Firebase に移動します。
- [プロジェクトを作成] をクリックし、プロジェクト名を入力します。
- 同意チェックボックスをオンにして、[続行] をクリックします。同意チェックボックスがない場合は、この手順をスキップできます。
- Firebase プロジェクトが作成されたら、プロジェクト ID を確認します。[プロジェクトの概要] に移動し、設定アイコン > [プロジェクトの設定] をクリックします。
- プロジェクトが [全般] タブに表示されます。
Firebase への接続
camerastream-start
ディレクトリに移動し、Actions プロジェクトに Firebase CLI を設定します。
$ cd camerastream-start $ firebase use <firebase-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 コンソールで、[Build] > [Realtime Database] > [Create 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
},
}],
},
};
});
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 を処理するには、Firebase Hosting URL を functions/index.js
ファイルの allowlist
配列に追加します。
index.js
'use strict';
.....
var allowList = ['https://www.gstatic.com','https://<firebase-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 に移動します。
- [プロジェクトを作成] をクリックし、プロジェクトの名前を入力して [プロジェクトを作成] をクリックします。
クラウド間インテグレーションを選択する
デベロッパー コンソールの [プロジェクトのホーム] で、[クラウド間] の [クラウド間統合を追加] を選択します。
- 統合名を入力し、[デバイスタイプ] で [カメラ] を選択します。この名前は、後でデバイスをセットアップするときに Google Home アプリに表示されます。この Codelab では、表示名として「WebRTC Codelab」と入力しましたが、別の名前を使用することもできます。
- [アプリのブランディング] で、アプリアイコンの
png
ファイルをアップロードします。サイズは 144 x 144 ピクセルで、名前は
にします。.png
アカウントのリンクを有効にする
プロジェクトのデプロイ後にアカウント リンクを有効にする手順は次のとおりです。
- デベロッパー コンソールに移動して、プロジェクトを開きます。
- [Cloud-to-Cloud] セクションで、統合の横にある [開発] > [編集] をクリックします。
- [設定と構成] ページで [アカウントのリンク] セクションを見つけ、対応するテキスト ボックスに次の情報を入力します。
クライアント ID |
|
クライアント シークレット |
|
認証 URL |
|
トークンの URL |
|
- [保存] > [テスト] をクリックします。
5. 仮想 WebRTC カメラをテストする
- Firebase プロジェクトのデプロイ時に表示された Hosting の URL に移動します。次のインターフェース(CameraStream クライアント アプリ)が表示されます。
- [ローカル動画の解像度] パネルで、目的の動画を選択します。
- ウェブカメラとマイクにアクセスする権限を CameraStream クライアント アプリに付与します。ウェブカメラからの動画フィードがクライアントに表示されます。
スマートホーム CameraStream
アクションへのリンク
- Google Home アプリで、[追加] > [Works with Google] をタップします。
- 作成したアクションを検索して選択します。
- 後で必要になるため、一意の 5 文字の英数字コードをメモしておきます。
- [戻る] をタップします。Google Home アプリで、WebRTC カメラがストラクチャに追加されます。
WebRTC ストリームを開始する
- CameraStream クライアント アプリのウェブページで、最後のセクションの英数字コードを [アカウント リンク トークンの値] テキスト ボックスに入力し、[送信] をクリックします。
- Google スマートディスプレイ デバイスから WebRTC セッションを開始するには、次のいずれかを行います。
- 「OK Google, WebRTC カメラをストリーミングして」と話しかけます。
- Google スマートディスプレイ デバイスで、[ホーム コントロール] > [カメラ] > [WebRTC カメラ] をタップします。
Google スマートホームの CameraStream クライアント アプリで、Offer SPD と Answer SDP が正常に生成され、交換されたことを確認します。ウェブカメラからの画像は、WebRTC を使用して Google スマートディスプレイ デバイスにストリーミングされます。
6. 完了
これで、WebRTC プロトコルを使用してウェブカメラから Google Nest ディスプレイ デバイスにストリーミングする方法について学習しました。
その他の情報
- スマートホーム デバイスのトレイト
- Actions on Google: Node.js を使用したスマートホーム サンプル
- スマートホーム アクションのテストと共有