Criar um receptor da Web personalizado

1. Visão geral

Logotipo do Google Cast

Este codelab vai ensinar você a criar um app receptor da Web personalizado para abrir conteúdo em dispositivos compatíveis com Cast.

O que é o Google Cast?

O Google Cast permite que os usuários transmitam conteúdo de um dispositivo móvel para uma TV. Os usuários podem usar o dispositivo móvel ou o navegador Chrome para computador como controle remoto para tocar mídia na TV.

O SDK do Google Cast permite que seu app controle dispositivos compatíveis com Google Cast, como uma TV ou sistema de som. O SDK do Cast oferece os componentes de IU necessários de acordo com a Lista de verificação de design do Google Cast.

Essa lista é fornecida para facilitar a experiência do usuário do Google Cast e deixá-la mais previsível em todas as plataformas compatíveis. Saiba mais.

O que vamos criar?

Ao concluir este codelab, você terá um app HTML5 que funciona como seu receptor personalizado capaz de exibir conteúdo em vídeo em dispositivos compatíveis com Cast.

O que você vai aprender

  • Como se preparar para o desenvolvimento do receptor.
  • Os conceitos básicos de um receptor compatível com Cast baseado no framework de aplicativos de transmissão.
  • Como receber um vídeo de transmissão.
  • Como integrar o logger do Debug.
  • Como otimizar seu receptor para smart displays.

O que é necessário

Experiência

  • Você precisa ter conhecimento prévio em desenvolvimento para a Web.
  • Também é necessário ter conhecimento prévio de como assistir TV :)

Como você usará este tutorial?

Apenas leitura Leitura e exercícios

Como você classificaria sua experiência com a criação de apps da Web?

Iniciante Intermediário Proficiente

Como você classificaria sua experiência com o ato de assistir TV?

Iniciante Intermediário Proficiente

2. Fazer o download do exemplo de código

Você pode fazer download de todo o exemplo de código para seu computador…

e descompactar o arquivo ZIP salvo.

3. Como implantar o receptor localmente

Para usar o receptor da Web com um dispositivo de transmissão, ele precisa estar hospedado em algum lugar onde o dispositivo de transmissão possa alcançá-lo. Se você já tem um servidor compatível com https, pule as instruções a seguir e anote o URL, porque ele será necessário na próxima seção.

Se você não tiver um servidor disponível, use o Firebase Hosting ou o ngrok.

Executar o servidor

Depois de configurar o serviço da sua preferência, acesse app-start e inicie o servidor.

Anote o URL do receptor hospedado. Você precisará dele na próxima seção.

4. Registrar um aplicativo no Play Console

Você precisa registrar seu aplicativo para poder executar um receptor personalizado, conforme criado neste codelab, nos dispositivos Chromecast. Depois de registrar seu aplicativo, você receberá um ID de aplicativo que precisa ser usado pelo app remetente para realizar chamadas de API, como para iniciar um app receptor.

Imagem do Console para desenvolvedores do SDK do Google Cast com o botão "Adicionar novo app" destacado

Clique em "Adicionar novo aplicativo"

Imagem da tela "New Receiver Application" com a opção "Custom Receiver" destacada

Selecione "Custom Receiver", que é o que estamos criando.

Imagem da tela "Novo receptor personalizado" mostrando um URL que alguém está digitando no campo "URL do aplicativo receptor"

Digite os detalhes do novo destinatário usando o URL que você acessou.

na última seção. Anote o ID do aplicativo atribuído ao novo receptor.

Também é necessário registrar seu dispositivo com Google Cast para que ele possa acessar o aplicativo receptor antes da publicação. Assim que você publicar o app receptor, ele ficará disponível para todos os dispositivos com Google Cast. Para os fins deste codelab, é recomendável trabalhar com um app receptor não publicado.

Imagem do Console para desenvolvedores do SDK do Google Cast com o botão "Adicionar novo dispositivo" destacado

Clique em "Add new Device".

Imagem da caixa de diálogo "Add Cast Receiver Device"

Insira o número de série impresso na parte traseira do dispositivo de transmissão e dê um nome descritivo a ele. Também é possível encontrar o número de série transmitindo sua tela no Chrome ao acessar o Console do desenvolvedor do SDK do Google Cast

Leva de 5 a 15 minutos para que o receptor e o dispositivo estejam prontos para o teste. Após aguardar de 5 a 15 minutos, reinicie o dispositivo de transmissão.

5. Executar o app de amostra

Logotipo do Google Chrome

Enquanto aguardamos o novo app receptor ficar pronto para testar, vamos ver um exemplo de app receptor concluído. O receptor que criaremos será capaz de reproduzir mídia usando streaming com taxa de bits adaptável. Usaremos um conteúdo de amostra codificado para Dynamic Adaptive Streaming over HTTP (DASH).

No navegador, abra a ferramenta CaC (link em inglês).

Imagem da guia "Google Cast Connect & logger Controls" da ferramenta Command e Control (CaC)

  1. Você verá nossa ferramenta CaC.
  2. Use o ID do receptor de exemplo "CC1AD845" padrão e clique no botão "Definir ID do app".
  3. Clique no botão Transmitir no canto superior esquerdo e selecione seu dispositivo com Google Cast.

Imagem da guia "Google Cast Connect & logger Controls" da ferramenta Command and Control (CaC) indicando que ela está conectada a um app receptor

  1. Navegue até a guia "Load Media" na parte superior.

Imagem da guia "Load Media" da ferramenta Command and Control (CaC)

  1. Clique no botão "Carregar por conteúdo" para reproduzir um vídeo de amostra.
  2. O vídeo começará a ser reproduzido no dispositivo com Google Cast para mostrar a aparência básica da funcionalidade de receptor usando o receptor padrão.

6. Preparar o projeto inicial

Precisamos adicionar compatibilidade com o Google Cast ao app inicial que você transferiu por download. Veja alguns termos do Google Cast que vamos usar neste codelab:

  • Um app remetente é executado em um dispositivo móvel ou laptop.
  • Um aplicativo receptor é executado no dispositivo com Google Cast.

Agora está tudo pronto para você criar com base no projeto inicial usando seu editor de texto favorito:

  1. Selecione o diretório ícone de pastaapp-start no download do exemplo de código.
  2. Abra js/receiver.js e index.html.

Enquanto você trabalha neste codelab, o http-server precisa coletar as mudanças feitas. Se você perceber que não está, tente encerrar e reiniciar http-server.

Design de apps

O app receptor inicializa a sessão de transmissão e fica em espera até que uma solicitação LOAD (ou seja, o comando para abrir uma mídia) de um remetente seja recebida.

O app consiste em uma visualização principal, definida em index.html, e um arquivo JavaScript chamado js/receiver.js, com toda a lógica para fazer o receptor funcionar.

index.html

Esse arquivo HTML vai conter a IU do nosso app receptor. Por enquanto, ele está vazio, e vamos adicionar essa função a todo o codelab.

receptor.js

Este script gerenciará toda a lógica do nosso app receptor. No momento, ele é apenas um arquivo vazio, mas vamos transformá-lo em um receptor de transmissão totalmente funcional com apenas algumas linhas de código na próxima seção.

7. Um receptor de transmissão básico

Um receptor de Cast básico vai inicializar a sessão de transmissão na inicialização. Isso é necessário para informar a todos os aplicativos remetentes conectados que o receptor foi ativado. Além disso, o novo SDK vem pré-configurado para processar mídia de streaming com taxa de bits adaptável (usando DASH, HLS e Smooth Streaming) e arquivos MP4 simples prontos para uso. Vamos fazer um teste.

Inicialização

Adicione o seguinte código a index.html no cabeçalho:

<head>
  ...

  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

Adicione o seguinte código a index.html <body> antes de <footer> carregar receiver.js, para fornecer ao SDK do receptor espaço para mostrar a IU padrão do receptor que está enviando com o script que você acabou de adicionar.

<cast-media-player></cast-media-player>

Agora, precisamos inicializar o SDK em js/receiver.js, que consiste em:

  • adquirir uma referência a CastReceiverContext, seu ponto de entrada principal para todo o SDK do receptor;
  • armazenar uma referência ao PlayerManager, o objeto que processa a reprodução e fornece todos os hooks necessários para conectar sua própria lógica personalizada;
  • Inicializando o SDK chamando start() em CastReceiverContext.

Adicione o seguinte a js/receiver.js.

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

context.start();

8. Transmitir conteúdo de vídeo "básico"

Para os fins deste codelab, use a ferramenta CaC para testar seu novo receptor.

Aponte o navegador da Web para a ferramenta CaC (link em inglês).

Imagem da guia &quot;Google Cast Connect & logger Controls&quot; da ferramenta Command e Control (CaC)

Substitua o ID do app conforme registrado anteriormente no campo e clique em "Definir ID do app". Isso instrui a ferramenta a usar o receptor ao iniciar a sessão de transmissão.

Como transmitir mídia

De modo geral, para reproduzir mídia em um dispositivo de transmissão, o seguinte precisa acontecer:

  1. O remetente cria um objeto MediaInfo JSON pelo SDK do Cast que modela um item de mídia.
  2. O remetente se conecta ao dispositivo de transmissão para iniciar o aplicativo receptor.
  3. O receptor carrega o objeto MediaInfo com uma solicitação LOAD para reproduzir o conteúdo.
  4. O receptor monitora e monitora o status da mídia.
  5. O remetente envia comandos ao receptor para controlar a reprodução com base nas interações do usuário com o app remetente.

Nesta primeira tentativa básica, preencheremos o MediaInfo com um URL de recurso reproduzível (armazenado em MediaInfo.contentUrl).

Um remetente real usa um identificador de mídia específico do aplicativo no MediaInfo.contentId. O receptor usa o contentId como identificador para fazer as chamadas de API de back-end apropriadas para resolver o URL real do recurso e o definir como MediaInfo.contentUrl.. O receptor também processa tarefas como aquisição de licenças DRM ou injeção de informações sobre intervalos comerciais.

Vamos ampliar o receptor para fazer algo como na próxima seção. Por enquanto, clique no ícone de transmissão e selecione seu dispositivo para abrir o receptor.

Imagem da guia &quot;Google Cast Connect & logger Controls&quot; da ferramenta Command and Control (CaC) indicando que ela está conectada a um app receptor

Navegue até a guia "Load Media" e clique no botão "Load by Content". O receptor vai começar a reproduzir o conteúdo de exemplo.

Imagem da guia &quot;Load Media&quot; da ferramenta Command and Control (CaC)

O SDK do receptor já vem pronto para:

  • Inicializar a sessão de transmissão
  • Processar as solicitações LOAD recebidas de remetentes que contêm recursos reproduzíveis
  • Fornecer uma IU básica do player pronta para ser exibida na tela grande.

Fique à vontade para conhecer a ferramenta CaC e o código dela antes de passar para a próxima seção, em que vamos ampliar nosso receptor para falar com uma API de exemplo simples para atender às solicitações LOAD recebidas dos remetentes.

9. Integrar com uma API externa

De acordo com a forma como a maioria dos desenvolvedores interage com os receptores de transmissão em apps reais, vamos modificar nosso receptor para processar solicitações LOAD que fazem referência ao conteúdo de mídia pretendido pela chave de API, em vez de enviar um URL de recurso reproduzível.

Os apps costumam fazer isso porque:

  • O remetente pode não saber o URL do conteúdo.
  • O aplicativo Google Cast foi projetado para lidar com a autenticação, outras lógicas de negócios ou chamadas de API diretamente no receptor.

Essa funcionalidade é implementada principalmente no método PlayerManager setMessageInterceptor(). Isso permite que você intercepte mensagens recebidas por tipo e as modifique antes que cheguem ao gerenciador de mensagens interno do SDK. Nesta seção, estamos lidando com solicitações LOAD, em que vamos fazer o seguinte:

  • Ler a solicitação LOAD recebida e o contentId personalizado dela.
  • Faça uma chamada GET para nossa API para procurar o recurso de streaming pelo contentId dele.
  • Modifique a solicitação LOAD com o URL do stream.
  • Modifique o objeto MediaInformation para definir os parâmetros do tipo de stream.
  • Transmita a solicitação ao SDK para reprodução ou rejeite o comando se não for possível pesquisar a mídia solicitada.

A API de exemplo fornecida mostra os hooks do SDK para personalizar tarefas comuns de receptor, enquanto ainda conta com uma experiência pronta para uso.

API de exemplo

Acesse https://storage.googleapis.com/cpe-sample-media/content.json e confira nosso catálogo de vídeos de exemplo. O conteúdo inclui URLs para imagens de pôster no formato PNG, além dos streams DASH e HLS. Os streams DASH e HLS apontam para fontes de áudio e vídeo com multiplexação armazenadas em contêineres mp4 fragmentados.

{
  "bbb": {
    "author": "The Blender Project",
    "description": "Grumpy Bunny is grumpy",
    "poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
    "stream": {
      "dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
      "hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
    "title": "Big Buck Bunny"
  },
  "fbb_ad": {
    "author": "Google Inc.",
    "description": "Introducing Chromecast. The easiest way to enjoy [...]",
    "poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
    "stream": {
      "dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
      "hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
    "title": "For Bigger Blazes"
  },

  [...]

}

Na próxima etapa, vamos mapear a chave de cada entrada (por exemplo, bbb, fbb_ad) para o URL do stream depois que o receptor for chamado com uma solicitação LOAD.

Interceptar a solicitação LOAD

Nesta etapa, vamos criar um interceptador de carregamento com uma função que faz uma solicitação XHR ao arquivo JSON hospedado. Quando o arquivo JSON for recebido, vamos analisar o conteúdo e definir os metadados. Nas seções a seguir, vamos personalizar os parâmetros MediaInformation para especificar o tipo de conteúdo.

Adicione o seguinte código ao arquivo js/receiver.js, logo antes da chamada para context.start().

function makeRequest (method, url) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open(method, url);
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        resolve(JSON.parse(xhr.response));
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText
      });
    };
    xhr.send();
  });
}

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
        // Fetch content repository by requested contentId
        makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            reject();
          } else {
            // Add metadata
            let metadata = new
               cast.framework.messages.GenericMediaMetadata();
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
        });
      });
    });

A próxima seção descreve como configurar a propriedade media da solicitação de carregamento para conteúdo DASH.

Como usar o conteúdo DASH da API de exemplo

Agora que preparamos o interceptador para o carregamento, vamos especificar o tipo de conteúdo para o receptor. Essas informações vão fornecer ao destinatário o URL da playlist principal e o tipo MIME de stream. Adicione o seguinte código ao arquivo js/receiver.js no Promise() do interceptador LOAD:

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            ...
          }
        });
      });
    });

Depois de concluir essa etapa, acesse "Como testar" para tentar carregar com conteúdo DASH. Se você quiser testar o carregamento com conteúdo HLS, confira a próxima etapa.

Como usar o conteúdo HLS da API de exemplo

A API de exemplo inclui conteúdo HLS e DASH. Além de definir o contentType como fizemos na etapa anterior, a solicitação de carregamento precisará de algumas propriedades adicionais para usar os URLs HLS da API de exemplo. Quando o receptor está configurado para reproduzir streams HLS, o tipo de contêiner padrão esperado é o stream de transporte (TS, na sigla em inglês). Como resultado, o receptor tentará abrir os streams de MP4 de exemplo no formato TS se apenas a propriedade contentUrl for modificada. Na solicitação de carregamento, o objeto MediaInformation precisa ser modificado com propriedades adicionais para que o receptor saiba que o conteúdo é do tipo MP4, e não TS. Adicione o seguinte código ao seu arquivo js/receiver.js no interceptador para modificar as propriedades contentUrl e contentType. Adicione também as propriedades HlsSegmentFormat e HlsVideoSegmentFormat.

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.hls;
            request.media.contentType = 'application/x-mpegurl';
            request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
            request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
            ...
          }
        });
      });
    });

Como fazer testes

Mais uma vez, abra a ferramenta CaC (link em inglês) e defina o ID do app como o ID do app receptor. Selecione o dispositivo usando o botão Transmitir.

Navegue até a guia "Load Media". Desta vez, exclua o texto no campo "Content URL" ao lado do botão "Load by Content". Isso forçará o aplicativo a enviar uma solicitação LOAD contendo apenas a referência contentId à mídia.

Imagem da guia &quot;Load Media&quot; da ferramenta Command and Control (CaC)

Supondo que tudo tenha funcionado bem com suas modificações no receptor, o interceptador precisa cuidar da forma do objeto MediaInfo em algo que o SDK possa reproduzir na tela.

Clique no botão "Carregar por conteúdo" para ver se a mídia é reproduzida corretamente. Você pode mudar o ID do conteúdo para outro no arquivo content.json.

10. Otimizar para smart displays

Os smart displays são dispositivos com funcionalidade de toque que permitem que aplicativos receptores ofereçam suporte a controles ativados por toque.

Esta seção explica como otimizar o app receptor quando iniciado em smart displays e como personalizar os controles do player.

Como acessar os controles da IU

O objeto de controles de IU para smart displays pode ser acessado usando cast.framework.ui.Controls.GetInstance(). Adicione o seguinte código ao arquivo js/receiver.js acima de context.start():

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();

context.start();

Se você não usar o elemento <cast-media-player>, será necessário definir touchScreenOptimizedApp em CastReceiverOptions. Neste codelab, usamos o elemento <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Os botões de controle padrão são atribuídos a cada slot com base em MetadataType e MediaStatus.supportedMediaCommands.

Controles de vídeo

Para MetadataType.MOVIE, MetadataType.TV_SHOW e MetadataType.GENERIC, o objeto de controles de IU para smart displays será exibido como no exemplo abaixo.

Imagem de um vídeo reproduzindo controles da IU sobrepostos

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.QUEUE_NEXT

Controles de áudio

Para MetadataType.MUSIC_TRACK, o objeto de controles de IU para smart displays vai ser mostrado da seguinte forma:

Imagem de música tocando com controles da IU sobrepostos

  1. --playback-logo-image
  2. MusicTrackMediaMetadata.albumName
  3. MusicTrackMediaMetadata.title
  4. MusicTrackMediaMetadata.albumArtist
  5. MusicTrackMediaMetadata.images[0]
  6. MediaStatus.currentTime
  7. MediaInformation.duration
  8. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.NO_BUTTON

Como atualizar comandos de mídia compatíveis

O objeto de controles de IU também determina se um ControlsButton é mostrado ou não com base em MediaStatus.supportedMediaCommands.

Quando o valor de supportedMediaCommands for igual a ALL_BASIC_MEDIA, o layout de controle padrão será exibido da seguinte maneira:

Imagem dos controles do player de mídia: barra de progresso, botão &quot;Reproduzir&quot;, botões &quot;Avançar&quot; e &quot;Voltar&quot; ativados

Quando o valor de supportedMediaCommands for igual a ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, o layout de controle padrão será exibido da seguinte maneira:

Imagem dos controles do player de mídia: barra de progresso, botão &quot;Reproduzir&quot;, &quot;Pular para frente&quot; e &quot;Pular para trás&quot; e &quot;Ativar fila antes&quot; e &quot;Próxima fila&quot; ativados

Quando o valor de supportedMediaCommands for igual a PAUSE | QUEUE_PREV | QUEUE_NEXT, o layout de controle padrão será exibido da seguinte maneira:

Imagem dos controles do player de mídia: barra de progresso, botão &quot;Reproduzir&quot; e botões &quot;Fila anterior&quot; e &quot;Fila em seguida&quot; ativados

Quando as faixas de texto estiverem disponíveis, o botão de legenda será sempre mostrado em SLOT_1.

Imagem dos controles do player de mídia: barra de progresso, botão &quot;Reproduzir&quot;, &quot;Pular para frente&quot; e &quot;Voltar&quot;, botões &quot;Fila anterior&quot; e &quot;Fila de próximos&quot; e botões &quot;Closed captions&quot; ativados

Para mudar dinamicamente o valor de supportedMediaCommands depois de iniciar um contexto de receptor, chame PlayerManager.setSupportedMediaCommands para substituir o valor. Além disso, é possível adicionar um novo comando usando addSupportedMediaCommands ou remover um existente usando removeSupportedMediaCommands.

Como personalizar botões de controle

Você pode personalizar os controles usando PlayerDataBinder. Adicione o seguinte código ao arquivo js/receiver.js abaixo de touchControls para definir o primeiro slot dos controles:

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    // Clear default buttons and re-assign
    touchControls.clearDefaultSlotAssignments();
    touchControls.assignButton(
      cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
      cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
    );
  });

context.start();

11. Como implementar a navegação de mídia em smart displays

O navegador de mídia é um recurso receptor de CAF que permite que os usuários explorem mais conteúdo em dispositivos por toque. Para implementar isso, use PlayerDataBinder para definir a IU BrowseContent. Você pode preenchê-la com BrowseItems com base no conteúdo que quer exibir.

Conteúdo de navegação

Veja abaixo um exemplo da IU BrowseContent e as propriedades dela:

Imagem da IU do SearchContent mostrando duas miniaturas de vídeo e uma parte de uma

  1. BrowseContent.title
  2. BrowseContent.items

Proporção

Use a targetAspectRatio property para selecionar a melhor proporção para seus recursos de imagem. Três proporções são compatíveis com o SDK do receptor CAF: SQUARE_1_TO_1, PORTRAIT_2_TO_3 e LANDSCAPE_16_TO_9.

Procurar Item

Use BrowseItem para exibir o título, o subtítulo, a duração e a imagem de cada item:

Imagem da IU do SearchContent mostrando duas miniaturas de vídeo e uma parte de uma

  1. BrowseItem.image
  2. BrowseItem.duration
  3. BrowseItem.title
  4. BrowseItem.subtitle

Definir dados de navegação de mídia

Você pode fornecer uma lista de conteúdo de mídia para navegar chamando setBrowseContent. Adicione o seguinte código ao arquivo js/receiver.js abaixo do playerDataBinder e no listener de eventos MEDIA_CHANGED para definir os itens de navegação com um título "Up Next".

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

...

let browseItems = getBrowseItems();

function getBrowseItems() {
  let browseItems = [];
  makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
  .then(function (data) {
    for (let key in data) {
      let item = new cast.framework.ui.BrowseItem();
      item.entity = key;
      item.title = data[key].title;
      item.subtitle = data[key].description;
      item.image = new cast.framework.messages.Image(data[key].poster);
      item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
      browseItems.push(item);
    }
  });
  return browseItems;
}

let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    ....

    // Media browse
    touchControls.setBrowseContent(browseContent);
  });

Ao clicar em um item de navegação de mídia, o interceptador LOAD será acionado. Adicione o código abaixo ao interceptador LOAD para mapear o request.media.contentId para o request.media.entity do item de navegação de mídia:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      ...

      // Map contentId to entity
      if (request.media && request.media.entity) {
        request.media.contentId = request.media.entity;
      }

      return new Promise((resolve, reject) => {
            ...
        });
    });

Também é possível definir o objeto BrowseContent como null para remover a IU do navegador de mídia.

12. Como depurar apps receptores

O SDK do Cast Receiver oferece outra opção para os desenvolvedores depurarem facilmente os apps receptores usando a API CastDebuglogger e uma ferramenta de controle e controle (CaC, na sigla em inglês) complementar para capturar registros.

Inicialização

Para incorporar a API, adicione o script de origem CastDebugLogger ao arquivo index.html. A origem precisa ser declarada na tag <head> após a declaração do SDK do receptor do Google Cast.

<head>
  ...
  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <!-- Cast Debug Logger -->
  <script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>

Em js/receiver.js, na parte superior do arquivo e abaixo de playerManager, adicione o seguinte código para recuperar a instância CastDebugLogger e ativar o logger:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

Quando o gerador de registros de depuração estiver ativado, uma sobreposição com DEBUG MODE será exibida no receptor.

Imagem de um vídeo sendo reproduzido com uma mensagem &quot;MODO DE DEPURAÇÃO&quot; em um fundo vermelho, no canto superior esquerdo do frame

Registrar eventos do player

Com o CastDebugLogger, é possível registrar facilmente os eventos do player disparados pelo SDK do receptor CAF e usar diferentes níveis de geração de registros para registrar os dados do evento. A configuração loggerLevelByEvents usa cast.framework.events.EventType e cast.framework.events.category para especificar quais eventos serão registrados.

Adicione o seguinte código abaixo da declaração castDebugLogger para registrar quando um evento CORE do jogador for acionado ou uma mudança de mediaStatus for transmitida:

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

Mensagens de registro e tags personalizadas

A API CastDebuglogger permite criar mensagens de registro que aparecem na sobreposição de depuração do receptor com cores diferentes. Os seguintes métodos de registro estão disponíveis, listados em ordem decrescente de prioridade:

  • castDebugLogger.error(custom_tag, message);
  • castDebugLogger.warn(custom_tag, message);
  • castDebugLogger.info(custom_tag, message);
  • castDebugLogger.debug(custom_tag, message);

Para cada método de registro, o primeiro parâmetro é uma tag personalizada. Pode ser qualquer string de identificação que você considere significativa. O CastDebugLogger usa tags para filtrar os registros. O uso das tags é explicado em detalhes abaixo. O segundo parâmetro é a mensagem de registro.

Para mostrar os registros em ação, adicione-os ao interceptador LOAD.

playerManager.setMessageInterceptor(
  cast.framework.messages.MessageType.LOAD,
  request => {
    castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');

    // Map contentId to entity
    if (request.media && request.media.entity) {
      request.media.contentId = request.media.entity;
    }

    return new Promise((resolve, reject) => {
      // Fetch content repository by requested contentId
      makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
        .then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            castDebugLogger.error(LOG_TAG, 'Content not found');
            reject();
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);

            // Add metadata
            let metadata = new cast.framework.messages.MovieMediaMetadata();
            metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
      });
    });
  });

É possível controlar quais mensagens aparecem na sobreposição de depuração definindo o nível de registro em loggerLevelByTags para cada tag personalizada. Por exemplo, ativar uma tag personalizada com o nível de registro cast.framework.LoggerLevel.DEBUG exibirá todas as mensagens adicionadas com erro, aviso, informações e mensagens de registro de depuração. Ativar uma tag personalizada com o nível WARNING só vai mostrar mensagens de erro e de registro.

A configuração loggerLevelByTags é opcional. Se uma tag personalizada não estiver configurada para o nível de registrador, todas as mensagens de registro vão ser exibidas na sobreposição de depuração.

Adicione o seguinte código abaixo do agente de registro de eventos CORE:

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
    [LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};

Depurar sobreposição

O Explorador de depuração de transmissão oferece uma sobreposição de depuração no receptor para exibir suas mensagens de registro personalizadas no dispositivo de transmissão. Use showDebugLogs para alternar a sobreposição de depuração e clearDebugLogs para limpar as mensagens de registro na sobreposição.

Adicione o código a seguir para visualizar a sobreposição de depuração no seu receptor.

context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      // Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
      castDebugLogger.setEnabled(true);

      // Show debug overlay
      castDebugLogger.showDebugLogs(true);

      // Clear log messages on debug overlay
      castDebugLogger.clearDebugLogs();
  }
});

Imagem mostrando a sobreposição de depuração, uma lista de mensagens de registro de depuração em um plano de fundo translúcido sobre um frame de vídeo

13. Parabéns

Agora você sabe criar um app receptor da Web personalizado usando o SDK do receptor da Web do Cast.

Para mais detalhes, consulte o guia do desenvolvedor sobre Web Receiver.