Implementar o CameraStream com WebRTC

1. Antes de começar

A característica CameraStream pertence a dispositivos com capacidade de transmitir feeds de vídeo para telas inteligentes, dispositivos Chromecast e smartphones. O protocolo WebRTC agora tem suporte no atributo CameraStream, o que significa que você pode reduzir muito a latência de inicialização e streaming de um dispositivo de câmera para um dispositivo de tela Google Nest.

Dispositivos de câmera fazendo streaming para uma tela Google Nest

Pré-requisitos

O que você vai aprender

  • Como implantar um serviço de casa inteligente em nuvem.
  • Como conectar seu serviço ao Google Assistente.
  • Como transmitir para um dispositivo de 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 uso) do Firebase.
  • Um dispositivo de webcam integrado ou externo que ofereça suporte à resolução full HD.
  • Um dispositivo de tela Google Nest

2. Primeiros passos

instalar a CLI do Firebase

A CLI do Firebase permite veicular seus apps da Web localmente e implantá-los no Firebase Hosting.

Para instalar a CLI do Firebase, siga estas etapas:

  1. No 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 um projeto

  1. Acesse o Google Home Developer Console.
  2. Clique em Criar projeto, insira um nome e clique em Criar projeto.

Nome do projeto

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 da casa inteligente do Google.

Para executar o app cliente CameraStream WebRTC, faça o seguinte:

  • Clique no botão abaixo 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 seguintes diretórios:

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

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

  • O subdiretório public, que contém uma IU de front-end para controlar e monitorar o estado do dispositivo da câmera com facilidade.
  • 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.

Crie um projeto do Firebase

  1. Acesse o Firebase.
  2. Clique em Criar um projeto e insira o nome do projeto.
  3. Marque a caixa de seleção do contrato e clique em Continuar. Se não houver uma caixa de seleção de acordo, pule esta etapa.
    Criar projeto do Firebase
  4. Depois que o projeto do Firebase for criado, encontre o ID dele. Acesse Visão geral do projeto e clique no ícone de configurações > Configurações do projeto.
    Abrir as configurações do projeto
  5. Seu projeto está listado na guia Geral.
    Configurações gerais do projeto

Conectar-se ao Firebase

  1. Acesse o diretório camerastream-start e configure a CLI do Firebase com seu projeto do Actions:
$ cd camerastream-start
$ firebase use <firebase-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 você receber a mensagem abaixo, ignore-a. Esse aviso é devido a dependências mais antigas. Para mais informações, 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 seu 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 não substitua os arquivos index.js e package.json da 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. Troca de mensagens do protocolo de descrição de sessão (SDP)

A troca de mensagens SDP é uma etapa importante no estabelecimento de um stream do 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 a webcam e o app cliente CameraStream da casa inteligente, siga estas etapas:

  1. No console do Firebase, clique em Build > Realtime Database > Create database.

Página do Realtime Database no console do Firebase

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

Menu suspenso do local do Realtime Database na caixa de diálogo &quot;Configurar banco de dados&quot;

  1. Selecione Iniciar no modo de teste e clique em Ativar. Com o Realtime Database ativado, você precisa 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 seu 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 mostrar 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 para o console para concluir o processo. O app da Web recém-criado aparece na página Project settings.

4. Criar uma câmera WebRTC

Agora que você configurou a ação, seu serviço em 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 dos recursos deles.
  • Uma intent EXECUTE/QUERY que ocorre quando o Google Assistente quer controlar um dispositivo em nome do usuário. Você deve responder com um payload JSON com o status de execução de cada dispositivo solicitado.

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

Atualizar a resposta SYNC

  1. Navegue até o arquivo functions/index.js. Ele contém o código para responder a solicitações do Google Assistente.
  2. Edite a intent SYNC para retornar os metadados e os 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
      },
    }],
  },
};
});
  1. USER_ID não está definido no código. Adicione o seguinte em const _ = require('underscore');:
// Hardcoded user ID
const USER_ID = '123';

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';
.....

var allowList = ['https://www.gstatic.com','https://<firebase-project-id>.web.app']; //TODO Add Firebase hosting URL.

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

Processar o encerramento do stream

Para processar o encerramento do stream do WebRTC, adicione o URL da função "signaling" 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

O comando implanta um app da Web e várias Cloud Functions para Firebase:

...

✔ Deploy complete!

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

Configurar seu projeto do Google Developer Console

  1. Acesse o console do desenvolvedor.
  2. Clique em Criar projeto, insira um nome e clique em Criar projeto.

Nome do projeto

Selecionar a integração entre nuvens

Na página Início do projeto do console do desenvolvedor, selecione Adicionar integração entre nuvens em Entre nuvens.

Adicionar a integração entre nuvens

  1. Digite um nome de integração e selecione Câmera em Tipo de dispositivo. Esse nome vai aparecer no app Google Home mais tarde, quando houver um dispositivo para configurar. Para este codelab, inserimos WebRTC Codelab como o nome de exibição, mas você pode usar um nome diferente.

Adicionar um nome de exibição

  1. Em Marca do app, faça upload de um arquivo png para o ícone do app, com tamanho de 144 x 144 px e nome .png.

Adicionar um ícone de app

Ativar a vinculação de contas

Para ativar a vinculação de contas depois que o projeto for implantado, siga estas etapas:

  1. Acesse o console do desenvolvedor e abra o projeto.
  2. Na seção De nuvem para nuvem, clique em Desenvolver > Editar ao lado da integração.
  3. Na página Configuração e configuração, encontre a seção Vinculação de contas e insira as seguintes informações nas caixas de texto correspondentes:

ID do cliente

ABC123

Chave secreta do cliente

DEF456

URL de autorização

https://us-central1-
.cloudfunctions.net/fakeauth

URL do token

https://us-central1-
.cloudfunctions.net/faketoken

Atualizar URLs de vinculação de conta

  1. Clique em Salvar > Testar.

5. Testar a câmera virtual do WebRTC

  1. Acesse o URL do Hosting que você viu ao implantar seu projeto do Firebase. A interface a seguir, que é o app cliente do CameraStream, vai aparecer:

Interface do app cliente CameraStream

  1. No painel Resolução de vídeo local, selecione o vídeo desejado.
  2. Permita que o app cliente CameraStream acesse sua webcam e 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. Pesquise 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 de cinco caracteres porque você vai precisar dele mais tarde.

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

  1. Toque em Voltar. A câmera WebRTC é adicionada à sua 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 Account linking token value e clique em Submit.

Caixa de texto do valor do token de vinculação de contas

  1. Para iniciar uma sessão do WebRTC no seu dispositivo de smart display do Google, faça o seguinte:
  • Diga "Ok Google, transmitir a câmera WebRTC".
  • No dispositivo Google Smart Display, toque em Controle da casa > Câmera > Câmera WebRTC.

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

6. Parabéns

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

Saiba mais