1. 始める前に
CameraStream
トレイトは、動画フィードをスマートディスプレイ、Chromecast デバイス、スマートフォンにストリーミングできるデバイスに使用します。WebRTC プロトコルが CameraStream
トレイトでサポートされるようになりました。これにより、カメラデバイスから Google Nest ディスプレイ デバイスへの起動とストリーミングの遅延を大幅に短縮できます。
前提条件
- Cloud-to-Cloud 入門を確認する。
学習内容
- スマートホーム クラウド サービスをデプロイする方法。
- サービスを 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](スマートホーム)> [Start building](作成を開始)をクリックします。Actions Console でプロジェクトが開きます。
- [Develop] > [Invocation] をクリックします。
- [Display name] テキスト ボックスにアクションの名前を入力し、[Save] をクリックします。この名前は、後でセットアップするデバイスがあるときに Google Home アプリに表示されます。この Codelab では表示名として
WebRTC Codelab
を入力しましたが、別の名前を使用することもできます。
- [操作] をクリックします。
- [Fulfillment 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
ディレクトリに移動し、Firebase CLI に Actions プロジェクトを設定します。
$ 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 の「signaling」関数の 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 で、[開発] > [アカウントのリンク] を選択します。
- [OAuth クライアント情報] セクションで、対応するテキスト ボックスに次の情報を入力します。
Client-ID |
|
クライアント シークレット |
|
認証 URL |
|
トークン URL |
|
- [Save] > [Test] をクリックします。
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 を使用したスマートホームのサンプル
- スマートホーム アクションのテストと共有