Implementare CameraStream con WebRTC

1. Prima di iniziare

Il trait CameraStream appartiene ai dispositivi in grado di riprodurre in streaming i feed video su smart display, dispositivi Chromecast e smartphone. Il protocollo WebRTC è ora supportato all'interno del trait CameraStream, il che significa che puoi ridurre notevolmente la latenza di avvio e di streaming da un dispositivo videocamera a un display Google Nest.

Streaming dei dispositivi della videocamera su un display Google Nest

Prerequisiti

Cosa imparerai a fare

  • Come eseguire il deployment di un servizio cloud per la smart home.
  • Come collegare il tuo servizio all'Assistente Google.
  • Come trasmettere in streaming su un display Google Nest con il protocollo WebRTC.

Che cosa ti serve

  • Un browser web, ad esempio Google Chrome.
  • Un dispositivo iOS o Android con l'app Google Home.
  • Node.js 10.16 o versioni successive.
  • Piano Blaze (con pagamento a consumo) per Firebase.
  • Una webcam integrata o esterna in grado di supportare la risoluzione Full HD.
  • Un display Google Nest.

2. Inizia

Installa l'interfaccia a riga di comando di Firebase

L'interfaccia a riga di comando di Firebase ti consente di gestire le app web in locale e di eseguirne il deployment su Firebase Hosting.

Per installare l'interfaccia a riga di comando di Firebase, segui questi passaggi:

  1. Nel terminale, scarica e installa l'interfaccia a riga di comando di Firebase:
$ npm install -g firebase-tools
  1. Verifica che l'interfaccia a riga di comando sia installata correttamente:
$ firebase --version
  1. Autorizza l'interfaccia a riga di comando di Firebase con il tuo Account Google:
$ firebase login

Creare e configurare un progetto Actions

  1. Vai alla Console di Actions e fai clic su Nuovo progetto.
  2. Nella casella di testo Nome progetto, inserisci un nome per il progetto e fai clic su Crea progetto.

La finestra di dialogo Nuovo progetto nella console di Actions

  1. Nella pagina Che tipo di azione vuoi creare?, fai clic su Smart home > Inizia a costruire. Il progetto si apre nella console di Actions.

La scheda Panoramica nella console di Actions

  1. Fai clic su Sviluppa > Chiamata.
  2. Nella casella di testo Nome visualizzato, inserisci un nome per l'Azione e fai clic su Salva. Questo nome verrà visualizzato nell'app Google Home più tardi, quando c'è un dispositivo da configurare. Per questo codelab, abbiamo inserito WebRTC Codelab come nome visualizzato, ma puoi usare un nome diverso.

Riquadro Chiamata nella console di Actions

  1. Fai clic su Azioni.
  2. Nella casella di testo URL di evasione, inserisci un URL segnaposto, ad esempio https://example.com.

Esegui l'app client CameraStream

Il codice sorgente per questo codelab include un client WebRTC che stabilisce, negozia e gestisce la sessione WebRTC tra la webcam e il dispositivo di visualizzazione per la smart home di Google.

Per eseguire l'app client WebRTC di CameraStream, procedi in uno dei seguenti modi:

  • Fai clic sul pulsante seguente per scaricare il codice sorgente nella macchina di sviluppo:

  • Clona questo repository GitHub:
$ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git

Il codice contiene le seguenti directory:

  • La directory camerastream-start, che contiene il codice di avvio su cui si crea la build.
  • La directory camerastream-done, che contiene il codice della soluzione per il codelab completato.

La directory camerastream-start contiene le seguenti sottodirectory:

  • La sottodirectory public, che contiene un'interfaccia utente frontend per controllare e monitorare facilmente lo stato della videocamera.
  • La sottodirectory functions, che contiene un servizio cloud completamente implementato che gestisce la videocamera con Cloud Functions for Firebase e Realtime Database.

Il codice di avvio contiene commenti TODO che indicano dove è necessario aggiungere o modificare il codice, come nell'esempio seguente:

// TODO: Implement full SYNC response.

Connessione a Firebase

  1. Vai alla directory camerastream-start e configura l'interfaccia a riga di comando di Firebase con il tuo progetto Actions:
$ cd camerastream-start
$ firebase use PROJECT_ID
  1. Nella directory camerastream-start, vai alla cartella functions e installa tutte le dipendenze necessarie:
$ cd functions
$ npm install
  1. Se viene visualizzato il seguente messaggio, ignoralo. Questo avviso è dovuto a dipendenze meno recenti. Per maggiori informazioni, consulta questo problema su GitHub.
found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details
  1. Inizializza un progetto Firebase:
$ firebase init
  1. Seleziona Funzioni e Hosting. Questo comando inizializza le API e le funzionalità necessarie per il progetto.
? 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
  1. Configura Cloud Functions con i file predefiniti e assicurati di non sovrascrivere i file index.js e package.json esistenti nell'esempio del progetto:
? 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
  1. Configura Hosting con la directory public nel codice del progetto e utilizza il file index.html esistente:
? 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. Messaggi SDP (Exchange Session Description Protocol)

Lo scambio di messaggi SDP è un passaggio importante nella creazione di uno stream WebRTC. SDP è un protocollo basato su testo che descrive le caratteristiche di una sessione multimediale. Viene utilizzato in WebRTC per negoziare i parametri di una connessione peer-to-peer, come i codec utilizzati, gli indirizzi IP dei partecipanti e le porte utilizzate per il trasporto multimediale.

Per utilizzare Realtime Database come host per scambiare messaggi SDP tra la tua webcam e l'app client CameraStream per la smart home, segui questi passaggi:

  1. Nella console di Firebase, fai clic su Crea > Realtime Database > Crea database.

La pagina Realtime Database nella console Firebase

  1. Nel menu a discesa Posizione di Realtime Database, seleziona una località appropriata da cui ospitare il tuo database.

Il menu a discesa Località di Realtime Database nella finestra di dialogo Imposta database

  1. Seleziona Avvia in modalità di test e fai clic su Attiva. Con Realtime Database abilitato, devi avere la possibilità di farvi riferimento dall'app client CameraStream.
  1. Nella console Firebase, seleziona 513f2be95dcd7896.png Impostazioni progetto > Impostazioni progetto > e584a9026e2b407f.pngAggiungi Firebase alla tua applicazione web per avviare il flusso di lavoro di configurazione.
  2. Se hai già aggiunto un'app al tuo progetto Firebase, fai clic su Aggiungi app per visualizzare le opzioni della piattaforma.
  3. Inserisci un nickname per l'app, ad esempio My web app, quindi fai clic su Registra app.
  4. Nella sezione Aggiungi SDK Firebase, seleziona Utilizza il tag <script>.
  5. Copia i valori dall'oggetto firebasebaseConfig e incollali nel file camaerastream-start/public/webrtc_generator.js.
const firebaseConfig = {
  apiKey: "XXXXX",
  authDomain: "XXXXX",
  projectId: "XXXXX",
  storageBucket: "XXXXX",
  messagingSenderId: "XXXXX",
  appId: "XXXXX",
  measurementId: "XXXXX"
};
  1. Fai clic su Vai alla console per completare la procedura. L'app web appena creata viene visualizzata nella pagina Impostazioni progetto.

4. Crea una videocamera WebRTC

Ora che hai configurato l'Azione, il tuo servizio cloud deve gestire i seguenti intent:

  • Un intent SYNC che si verifica quando l'assistente vuole sapere quali dispositivi ha connesso l'utente. Viene inviato al tuo servizio quando l'utente collega un account. Dovresti rispondere con un payload JSON dei dispositivi dell'utente e delle loro funzionalità.
  • Un intent EXECUTE/QUERY che si verifica quando l'assistente vuole controllare un dispositivo per conto di un utente. Devi rispondere con un payload JSON con lo stato di esecuzione di ogni dispositivo richiesto.

In questa sezione aggiornerai le funzioni di cui hai eseguito il deployment in precedenza per gestire questi intent.

Aggiorna la risposta SYNC

  1. Vai al file functions/index.js. Contiene il codice per rispondere alle richieste dell'assistente.
  2. Modifica l'intent SYNC per restituire i metadati e le funzionalità del dispositivo:

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
        },
      }],
    },
  };
});

Gestire l'intent EXECUTE

L'intent EXECUTE gestisce i comandi per aggiornare lo stato del dispositivo. La risposta restituisce lo stato di ciascun comando, ad esempio SUCCESS, ERROR o PENDING, e il nuovo stato del dispositivo.

  • Per gestire un intent EXECUTE, modifica l'intent EXECUTE in modo che restituisca un endpoint signaling del progetto Firebase nel file functions/index.js:

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],
    },
  };

Gestire la condivisione delle risorse tra origini (CORS)

  • Per gestire CORS a causa dell'utilizzo del metodo POST per inviare l'SDP, aggiungi l'URL di Firebase Hosting all'array allowlist nel file functions/index.js:

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.

Per ulteriori informazioni su CORS, consulta Condivisione delle risorse tra origini (CORS).

Gestire la terminazione dello stream

  • Per gestire la terminazione del flusso WebRTC, aggiungi l'URL della funzione "segnalazione" di Firebase al file 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();

Esegui il deployment in Firebase

  • Per eseguire il deployment su Firebase, esegui il deployment del Cloud fulfillment aggiornato con l'interfaccia a riga di comando di Firebase:
$ firebase deploy

Questo comando esegue il deployment di un'app web e di diverse Cloud Functions for Firebase:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.web.app

Abilita collegamento account

Per abilitare il collegamento dell'account dopo il deployment del progetto:

  1. Nella Console di Actions, seleziona Sviluppo > Collegamento dell'account.
  2. Nella sezione Informazioni client OAuth, inserisci le seguenti informazioni nelle caselle di testo corrispondenti:

Client-ID

ABC123

Client secret

DEF456

URL di autorizzazione

https://us-central1-{project-id}.cloudfunctions.net/fakeauth

URL token

https://us-central1-{project-id}.cloudfunctions.net/faketoken

La pagina di collegamento degli account in Actions Console

  1. Fai clic su Salva > Test.

5. Testa la videocamera WebRTC virtuale

  1. Vai all'URL di Hosting che hai visualizzato quando hai eseguito il deployment del progetto Firebase. Viene visualizzata la seguente interfaccia, che è l'app client CameraStream:

Interfaccia dell&#39;app client CameraStream

  1. Nel riquadro Risoluzione video locale, seleziona il video che ti interessa.
  2. Concedi all'app client CameraStream l'autorizzazione ad accedere a webcam e microfono. Sul client viene visualizzato un feed video proveniente dalla webcam.
  1. Nell'app Google Home, tocca Aggiungi > Funziona con Google.

La pagina Configurare un dispositivo nell&#39;app Google Home

  1. Cerca l'azione che hai creato e selezionala.

L&#39;azione per la smart home nell&#39;app Google Home

  1. Prendi nota del codice alfanumerico univoco di cinque caratteri, perché ne avrai bisogno in seguito.

Il codice alfanumerico univoco a cinque cifre

  1. Tocca Torna indietro. La videocamera WebRTC viene aggiunta alla tua struttura nell'app Google Home.

Avviare uno stream WebRTC

  1. Nella pagina web dell'app client CameraStream, inserisci il codice alfanumerico dell'ultima sezione nella casella di testo Valore del token di collegamento dell'account, quindi fai clic su Invia.

La casella di testo Valore del token di collegamento dell&#39;account

  1. Per avviare una sessione WebRTC dal tuo smart display Google, esegui una delle seguenti operazioni:
  • Di' "Hey Google, riproduci in streaming la videocamera WebRTC".
  • Sul tuo smart display Google, tocca Controllo della casa > Fotocamera > Videocamera WebRTC.

Dall'app client CameraStream per la smart home di Google, vedrai che l'SPD dell'offerta e l'SDP delle risposte sono stati generati e scambiati correttamente. L'immagine della tua webcam viene riprodotta in streaming sul tuo smart display Google con WebRTC.

6. Complimenti

Complimenti! Hai imparato a trasmettere in streaming dalla webcam a un display Google Nest con il protocollo WebRTC.

Scopri di più