Implementar o CameraStream com WebRTC

1. Antes de começar

A característica CameraStream pertence a dispositivos com a capacidade de fazer streaming de feeds de vídeo para smart displays, dispositivos Chromecast e smartphones. O protocolo WebRTC agora tem suporte na característica CameraStream, o que significa que é possível reduzir bastante a latência de inicialização e streaming de um dispositivo de câmera para uma tela Google Nest.

Câmeras fazendo streaming para uma tela Google Nest

Pré-requisitos

Neste curso, você vai aprender a:

  • Como implantar um serviço de casa inteligente na nuvem.
  • Como conectar seu serviço ao Google Assistente.
  • Como fazer streaming para uma tela Google Nest com o protocolo WebRTC.

O que é necessário

  • Um navegador da Web, como o Google Chrome
  • Um dispositivo iOS ou Android com o app Google Home.
  • Node.js versão 10.16 ou mais recente
  • Plano Blaze (pagamento por utilização) para o Firebase.
  • Um dispositivo de webcam integrado ou externo compatível com a resolução Full HD.
  • Uma tela Google Nest

2. Primeiros passos

instalar a CLI do Firebase

Com a CLI do Firebase, é possível disponibilizar seus apps da Web localmente e implantá-los no Firebase Hosting.

Para instalar a CLI do Firebase, siga estas etapas:

  1. No seu terminal, faça o download e instale a CLI do Firebase:
$ npm install -g firebase-tools
  1. Verifique se a CLI foi instalada corretamente:
$ firebase --version
  1. Autorize a CLI do Firebase com sua Conta do Google:
$ firebase login

Criar e configurar um projeto do Actions

  1. Acesse o Console do Actions e clique em Novo projeto.
  2. Na caixa de texto Nome do projeto, insira um nome e clique em Criar projeto.

A caixa de diálogo "Novo projeto" no Console do Actions

  1. Na página Que tipo de ação você quer criar?, clique em Casa inteligente > Começar a criar. O projeto é aberto no Console do Actions.

Guia "Visão geral" no Console do Actions

  1. Clique em Develop > Invocation.
  2. Na caixa de texto Nome de exibição, digite um nome para a ação e clique em Salvar. Esse nome vai aparecer no app Google Home mais tarde, quando houver um dispositivo para configurar. Neste codelab, inserimos WebRTC Codelab como o nome de exibição, mas você pode usar um nome diferente.

O painel de invocação no Console do Actions

  1. Clique em Ações.
  2. Na caixa de texto URL de fulfillment, insira um URL de marcador, como https://example.com.

Executar o app cliente CameraStream

O código-fonte deste codelab inclui um cliente WebRTC que estabelece, negocia e gerencia a sessão WebRTC entre a webcam e o dispositivo de tela de casa inteligente do Google.

Para executar o app cliente WebRTC do CameraStream, siga um destes procedimentos:

  • Clique no botão a seguir para fazer o download do código-fonte para sua máquina de desenvolvimento:

  • Clone este repositório do GitHub:
$ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git

O código contém os diretórios abaixo:

  • O diretório camerastream-start, que contém o código inicial que você vai usar como base.
  • O diretório camerastream-done, que contém o código da solução do codelab concluído.

O diretório camerastream-start contém os seguintes subdiretórios:

  • O subdiretório public, que contém uma interface de front-end para controlar e monitorar facilmente o estado do dispositivo de câmera.
  • O subdiretório functions, que contém um serviço de nuvem totalmente implementado que gerencia a câmera com o Cloud Functions para Firebase e o Realtime Database.

O código inicial contém comentários TODO que indicam onde você precisa adicionar ou mudar o código, como no exemplo a seguir:

// TODO: Implement full SYNC response.

Conectar ao Firebase

  1. Navegue até o diretório camerastream-start e configure a CLI do Firebase com seu projeto do Actions:
$ cd camerastream-start
$ firebase use PROJECT_ID
  1. No diretório camerastream-start, navegue até a pasta functions e instale todas as dependências necessárias:
$ cd functions
$ npm install
  1. Se a mensagem a seguir aparecer, ignore-a. Esse aviso se deve a dependências mais antigas. Para saber mais, consulte este problema no GitHub.
found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details
  1. Inicialize um projeto do Firebase:
$ firebase init
  1. Selecione Functions e Hosting. Isso inicializa as APIs e os recursos necessários para o projeto.
? 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. Configure o Cloud Functions com os arquivos padrão e verifique se você não substitui os arquivos index.js e package.json atuais na amostra do projeto:
? 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. Configure o Hosting com o diretório public no código do projeto e use o arquivo index.html atual:
? 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. Mensagens do protocolo de descrição da sessão do Exchange (SDP, na sigla em inglês)

A troca de mensagens SDP é uma etapa importante no estabelecimento de um stream WebRTC. O SDP é um protocolo baseado em texto que descreve as características de uma sessão multimídia. Ele é usado no WebRTC para negociar os parâmetros de uma conexão ponto a ponto, como os codecs usados, os endereços IP dos participantes e as portas usadas para o transporte de mídia.

Para usar o Realtime Database como host para trocar mensagens SDP entre sua webcam e o app cliente CameraStream de casa inteligente, siga estas etapas:

  1. No Console do Firebase, clique em Build > Realtime Database > Criar banco de dados.

Página do Realtime Database no Console do Firebase

  1. No menu suspenso Local do Realtime Database, selecione um local apropriado para hospedar seu banco de dados.

O menu suspenso de local do Realtime Database na caixa de diálogo "Configurar banco de dados"

  1. Selecione Iniciar no modo de teste e clique em Ativar. Com o Realtime Database ativado, é preciso fazer referência a ele no app cliente CameraStream.
  1. No Console do Firebase, selecione 513f2be95dcd7896.png Configurações do projeto > Configurações do projeto > e584a9026e2b407f.pngAdicionar o Firebase ao app da Web para iniciar o fluxo de trabalho de configuração.
  2. Se você já adicionou um app ao seu projeto do Firebase, clique em Adicionar app para exibir as opções da plataforma.
  3. Digite um apelido para o app, como My web app, e clique em Registrar app.
  4. Na seção Adicionar SDK do Firebase, selecione Usar tag <script>.
  5. Copie os valores do objeto firebasebaseConfig e cole-os no arquivo camaerastream-start/public/webrtc_generator.js.
const firebaseConfig = {
  apiKey: "XXXXX",
  authDomain: "XXXXX",
  projectId: "XXXXX",
  storageBucket: "XXXXX",
  messagingSenderId: "XXXXX",
  appId: "XXXXX",
  measurementId: "XXXXX"
};
  1. Clique em Continuar no console para concluir o processo. O app da Web recém-criado vai aparecer na página Configurações do projeto.

4. Criar uma câmera WebRTC

Agora que você configurou a ação, o serviço de nuvem precisa processar as seguintes intents:

  • Uma intent SYNC que ocorre quando o Google Assistente quer saber a quais dispositivos o usuário está conectado. Ela é enviada ao seu serviço quando o usuário vincula uma conta. Você deve responder com um payload JSON dos dispositivos do usuário e seus recursos.
  • Uma intent EXECUTE/QUERY que ocorre quando o Google Assistente quer controlar um dispositivo em nome de um usuário. Você deve responder com um payload JSON com o status de execução de cada dispositivo solicitado.

Nesta seção, você vai atualizar as funções implantadas para processar essas intents.

Atualizar a resposta SYNC

  1. Navegue até o arquivo functions/index.js. Ele contém o código para responder às solicitações do Google Assistente.
  2. Edite a intent SYNC para retornar os metadados e recursos do 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
        },
      }],
    },
  };
});

Processar a intent EXECUTE

A intent EXECUTE processa comandos para atualizar o estado do dispositivo. A resposta retorna o status de cada comando, como SUCCESS, ERROR ou PENDING, e o novo estado do dispositivo.

  • Para processar uma intent EXECUTE, edite a intent EXECUTE para retornar o endpoint signaling do projeto do Firebase no arquivo 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],
    },
  };

Processar o compartilhamento de recursos entre origens (CORS)

  • Para processar o CORS devido ao uso do método POST para enviar o SDP, adicione o URL do Firebase Hosting à matriz allowlist no arquivo 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.

Para mais informações sobre o CORS, consulte Compartilhamento de recursos entre origens (CORS).

Processar a terminação do stream

  • Para lidar com o encerramento do stream WebRTC, adicione o URL da função de "indicação" do Firebase ao arquivo 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();

Implantar no Firebase

  • Para implantar no Firebase, implante o fulfillment da nuvem atualizado com a CLI do Firebase:
$ firebase deploy

Este comando implanta um app da Web e várias funções do Cloud para Firebase:

...

✔ Deploy complete!

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

Ativar vinculação de contas

Para ativar a vinculação de contas após a implantação do projeto, siga estas etapas:

  1. No Console do Actions, selecione Desenvolver > Vinculação de contas.
  2. Na seção Informações do cliente OAuth, digite as seguintes informações nas caixas de texto correspondentes:

Client-ID

ABC123

Chave secreta do cliente

DEF456

URL de autorização

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

URL do token

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

A página de vinculação de conta no Console do Actions

  1. Clique em Save > Test.

5. Testar a câmera WebRTC virtual

  1. Navegue até o URL do Hosting que você viu quando implantou seu projeto do Firebase. Você verá a seguinte interface, que é o app cliente CameraStream:

Interface do app cliente do CameraStream

  1. No painel Resolução de vídeo local, selecione o vídeo desejado.
  2. Conceda permissão ao app cliente CameraStream para acessar a webcam e o microfone. Um feed de vídeo da sua webcam aparece no cliente.
  1. No app Google Home, toque em Adicionar > Compatível com o Google.

Página &quot;Configurar um dispositivo&quot; no app Google Home

  1. Procure e selecione a ação que você criou.

A ação de casa inteligente no app Google Home

  1. Anote o código alfanumérico exclusivo de cinco caracteres, porque você precisará dele mais tarde.

O código alfanumérico exclusivo de cinco dígitos

  1. Toque em Voltar. A câmera WebRTC é adicionada à estrutura no app Google Home.

Iniciar um stream WebRTC

  1. Na página da Web do app cliente CameraStream, insira o código alfanumérico da última seção na caixa de texto Valor do token de vinculação da conta e clique em Enviar.

A caixa de texto &quot;Valor do token de vinculação de conta&quot;

  1. Para iniciar uma sessão WebRTC no seu dispositivo smart display do Google, siga um destes procedimentos:
  • Diga "Ok Google, transmitir câmera WebRTC".
  • No dispositivo smart display do Google, toque em Automação residencial > Câmera > Câmera WebRTC.

No app cliente CameraStream da casa inteligente do Google, é possível conferir que o SPD de oferta e o SDP de resposta foram gerados e trocados. A imagem da webcam é transmitida para o dispositivo smart display do Google com WebRTC.

6. Parabéns

Parabéns! Você aprendeu a fazer streaming da webcam para um dispositivo de tela Google Nest com o protocolo WebRTC.

Saiba mais