1. Informações gerais
Este codelab ensinará você a criar um app receptor da Web personalizado para reproduzir 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. Eles poderão usar o dispositivo móvel ou o navegador Chrome do computador como um controle remoto para a reprodução de mídia na TV.
O SDK do Google Cast permite que seu app controle dispositivos compatíveis com Google Cast (por exemplo, uma TV ou um sistema de som). Ele fornece 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 de vídeo em dispositivos compatíveis com Cast.
Conteúdo
- Como configurar o desenvolvimento de receptor.
- Conceitos básicos de um receptor compatível com Cast com base no framework do aplicativo de transmissão.
- Como receber um vídeo transmitido.
- Como integrar o Debug Logger.
- Como otimizar seu receptor para smart displays.
Pré-requisitos
- A versão mais recente do navegador Google Chrome.
- Serviço de hospedagem HTTPS, como o Firebase Hosting ou o ngrok.
- Um dispositivo com Google Cast, como um Chromecast ou Android TV, configurado com acesso à Internet.
- Uma TV ou um monitor com entrada HDMI.
Experiência
- Você precisa ter conhecimento prévio em desenvolvimento da Web.
- Também é necessário ter conhecimento prévio de como assistir TV :)
Como você usará este tutorial?
Como você classificaria sua experiência com a criação de apps da Web?
Como você classificaria sua experiência com o ato de assistir TV?
2. Acessar o 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 seu receptor da Web com um dispositivo de transmissão, ele precisa estar hospedado em um lugar onde o dispositivo de transmissão possa alcançá-lo. Se você já tem um servidor compatível com HTTPS disponível, pule as instruções a seguir e anote o URL, porque você precisará dele 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 de sua preferência, acesse app-start
e inicie o servidor.
Anote o URL do seu receptor hospedado. Ele será usado na próxima seção.
4. Registrar um aplicativo no Console para desenvolvedores do Google Cast
Você precisa registrar seu aplicativo para executar um receptor personalizado, conforme criado neste codelab, em dispositivos Chromecast. Depois de registrar seu aplicativo, você receberá um ID que o aplicativo remetente deve usar para realizar chamadas de API, como iniciar um aplicativo receptor.
Clique em "Adicionar novo aplicativo"
Selecione "Custom Receiver", que é o que estamos criando.
Insira os detalhes do novo receptor usando o URL que você recebeu
na última seção. Anote o ID do aplicativo atribuído ao novo receptor.
Você também precisa registrar seu dispositivo com Google Cast para que ele possa acessar o aplicativo receptor antes de você publicá-lo. Assim que você publicar o aplicativo receptor, ele ficará disponível para todos os dispositivos com Google Cast. Para os fins deste codelab, é recomendável trabalhar com um aplicativo receptor não publicado.
Clique em "Adicionar novo dispositivo".
Insira o número de série impresso na parte de trás do seu dispositivo de transmissão e dê um nome descritivo a ele. Você também pode encontrar o número de série transmitindo a tela no Chrome ao acessar o Console para desenvolvedores do SDK do Google Cast.
Leva de 5 a 15 minutos até que o receptor e o dispositivo estejam prontos para o teste. Após esse período, reinicie o dispositivo de transmissão.
5. Executar o app de amostra
Enquanto aguardamos o novo aplicativo receptor ficar pronto para o teste, vejamos um exemplo de app receptor concluído. O receptor que criaremos será capaz de reproduzir mídia usando streaming de 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.
- Você verá a nossa ferramenta CaC.
- Use o exemplo de ID de receptor padrão "CC1AD845" e clique no botão "Definir ID do app".
- Clique no botão "Transmitir" no canto superior esquerdo e selecione seu dispositivo com Google Cast.
- Navegue até a guia "Load Media" na parte de cima.
- Clique no botão "Load by Content" para reproduzir um vídeo de amostra.
- O vídeo será reproduzido no dispositivo com Google Cast para mostrar a aparência da funcionalidade básica do 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 a terminologia do Google Cast que usaremos 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 criar com base no projeto inicial usando seu editor de texto favorito:
- Selecione o diretório
app-start
no download do exemplo de código. - Abra
js/receiver.js
eindex.html
.
Enquanto você trabalha neste codelab, o http-server
detecta as mudanças feitas. Se você perceber que ele não está acontecendo, tente encerrar e reiniciar o http-server
.
Design de apps
O app receptor inicializa a sessão do Google Cast e fica em espera até que uma solicitação LOAD (ou seja, o comando para reproduzir uma mídia) de um remetente chegue.
O app consiste em uma visualização principal, definida em index.html
, e um arquivo JavaScript chamado js/receiver.js
, que contém toda a lógica para fazer o receptor funcionar.
index.html
Esse arquivo HTML vai conter a interface do app receptor. Por enquanto, ele está vazio, e vamos adicioná-lo ao longo do codelab.
receiver.js
Esse script vai gerenciar toda a lógica do app receptor. No momento, ele é apenas um arquivo vazio, mas vamos transformá-lo em um receptor do Cast totalmente funcional com apenas algumas linhas de código na próxima seção.
7. Um receptor do Cast básico
Um receptor do Cast básico inicializará a sessão do Google Cast 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 em streaming com taxa de bits adaptável (usando DASH, HLS e Smooth Streaming) e arquivos MP4 simples. Vamos tentar.
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 código a seguir ao index.html
<body>
antes do <footer>
de receiver.js,
de carregamento para fornecer espaço ao SDK do receptor para mostrar a interface padrão, que é enviada 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:
- aquisição de uma referência ao
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. - inicializar o SDK chamando
start()
emCastReceiverContext
.
Adicione o código abaixo a js/receiver.js
.
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. Como transmitir conteúdo de vídeo "básico"
Para os fins deste codelab, use a ferramenta CaC para testar seu novo receptor.
Aponte seu navegador da Web para a ferramenta CaC (link em inglês).
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 abrir mídia em um dispositivo de transmissão, o seguinte precisa acontecer:
- O remetente cria um objeto
MediaInfo
JSON
do SDK do Cast que modela um item de mídia. - O remetente se conecta ao dispositivo de transmissão para iniciar o aplicativo receptor.
- O receptor carrega o objeto
MediaInfo
usando uma solicitaçãoLOAD
para reproduzir o conteúdo. - O receptor monitora e rastreia o status da mídia.
- O remetente envia comandos ao destinatário para controlar a reprodução com base nas interações do usuário com o app remetente.
Nesta primeira tentativa básica, vamos preencher MediaInfo
com um URL de recurso reproduzível (armazenado em MediaInfo.contentUrl
).
Um remetente real usa um identificador de mídia específico do app no MediaInfo.contentId
. O receptor usa o contentId
como um identificador para fazer chamadas adequadas à API de back-end, resolver o URL real do recurso e defini-lo como MediaInfo.contentUrl.
. Ele também processa tarefas como aquisição de licenças de DRM ou injeção de informações sobre intervalos de anúncios.
Vamos ampliar o receptor para fazer algo parecido na próxima seção. Por enquanto, clique no ícone de transmissão e selecione seu dispositivo para abrir o receptor.
Navegue até a guia "Load Media" e clique no botão "Load by Content". O receptor começará a reproduzir o conteúdo de amostra.
Então, o SDK do receptor já vem pronto para:
- Inicializar a sessão de transmissão
- Processar solicitações
LOAD
recebidas de remetentes que contêm recursos reproduzíveis - Fornece uma interface de player básica pronta para ser exibida na tela grande.
Fique à vontade para conhecer a ferramenta CaC e o código dela antes de prosseguir para a próxima seção. Vamos ampliar nosso receptor para falar com um exemplo de API simples a fim de 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 aplicativos reais, modificaremos o 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 por um URL de recurso jogável.
Os aplicativos geralmente fazem isso porque:
- O remetente pode não saber o URL do conteúdo.
- O aplicativo de transmissão foi projetado para processar autenticação, outras lógicas de negócios ou chamadas de API diretamente no receptor.
Essa funcionalidade é implementada principalmente no método setMessageInterceptor()
do PlayerManager
. Isso permite que você intercepte as mensagens recebidas por tipo e as modifique antes que cheguem ao gerenciador interno de mensagens do SDK. Nesta seção, estamos lidando com solicitações LOAD
e faremos o seguinte:
- Ler a solicitação
LOAD
recebida e ocontentId
personalizado dela. - Faça uma chamada
GET
para nossa API para procurar o recurso de streaming pelocontentId
. - 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 do receptor, sem deixar de contar com uma experiência praticamente pronta para uso.
API de exemplo
Acesse https://storage.googleapis.com/cpe-sample-media/content.json no navegador e confira nosso catálogo de vídeos de amostra. O conteúdo inclui URLs para imagens do pôster no formato PNG, além de streams DASH e HLS. Os streams DASH e HLS apontam para fontes de vídeo e áudio com multiplexação revertida 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 associar a chave de cada entrada (por exemplo, bbb, fbb_ad
) ao URL do stream depois que o receptor for chamado com uma solicitação LOAD
.
Interceptar a solicitação LOAD
Nesta etapa, criaremos um interceptador de carga com uma função que faz uma solicitação XHR
para o arquivo JSON
hospedado. Quando o arquivo JSON
for recebido, analisaremos o conteúdo e definiremos 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 seu arquivo js/receiver.js
, pouco 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.
Usar o conteúdo DASH da API de exemplo
Agora que preparamos o interceptador de carga, vamos especificar o tipo de conteúdo para o receptor. Essas informações fornecerão ao destinatário o URL da playlist principal e o tipo MIME do 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, avance para a seção "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 vai precisar de outras propriedades 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 amostra no formato TS se apenas a propriedade contentUrl
for modificada. Na solicitação de carregamento, o objeto MediaInformation
precisa ser modificado com mais propriedades 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 de carga 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;
...
}
});
});
});
Testar
Novamente, abra a ferramenta CaC e defina o ID do app como o ID do app receptor. Selecione seu dispositivo usando o botão Transmitir.
Navegue até a guia "Load Media". Desta vez, exclua o texto no campo "URL de conteúdo" ao lado do botão "Carregar conteúdo". Isso forçará o aplicativo a enviar uma solicitação LOAD
contendo apenas a referência contentId
à nossa mídia.
Supondo que tudo funcionou bem com suas modificações no receptor, o interceptador precisa transformar o objeto MediaInfo
em algo que o SDK possa reproduzir na tela.
Clique no botão "Load by Content" para conferir se a mídia é reproduzida corretamente. Você pode mudar o Content ID para outro no arquivo content.json.
10. Otimização para smart displays
Os smart displays são dispositivos com funcionalidade de toque que permitem que aplicativos receptores ofereçam suporte a controles por toque.
Esta seção explica como otimizar o aplicativo receptor quando iniciado em smart displays e como personalizar os controles do player.
Acessar os controles de interface
O objeto de controles de interface para smart displays pode ser acessado usando o cast.framework.ui.Controls.GetInstance()
. Adicione o seguinte código ao seu 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, estamos usando 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 interface para smart displays será exibido como no exemplo abaixo.
--playback-logo-image
MediaMetadata.subtitle
MediaMetadata.title
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
Controles de áudio
Para o MetadataType.MUSIC_TRACK
, o objeto de controles de interface para smart displays será mostrado da seguinte maneira:
--playback-logo-image
MusicTrackMediaMetadata.albumName
MusicTrackMediaMetadata.title
MusicTrackMediaMetadata.albumArtist
MusicTrackMediaMetadata.images[0]
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
Atualizar comandos de mídia compatíveis
O objeto de controles de interface também determina se um ControlsButton
é exibido ou não com base no MediaStatus.supportedMediaCommands
.
Quando o valor de supportedMediaCommands
for igual a ALL_BASIC_MEDIA
, o layout de controle padrão será exibido da seguinte forma:
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 forma:
Quando o valor de supportedMediaCommands for igual a PAUSE | QUEUE_PREV | QUEUE_NEXT
, o layout de controle padrão será exibido da seguinte forma:
Quando as faixas de texto estiverem disponíveis, o botão de legenda sempre será exibido em SLOT_1
.
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 comando existente usando removeSupportedMediaCommands
.
Como personalizar botões de controle
É possível 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 do receptor CAF que permite aos usuários explorar conteúdos adicionais em dispositivos touchscreen. Para implementar isso, use PlayerDataBinder
para definir a interface BrowseContent
. Em seguida, você pode preenchê-lo com BrowseItems
com base no conteúdo que você quer mostrar.
BrowseContent
Confira abaixo um exemplo da interface BrowseContent
e as propriedades dela:
BrowseContent.title
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
.
BrowseItem
Use BrowseItem
para exibir o título, o subtítulo, a duração e a imagem de cada item:
BrowseItem.image
BrowseItem.duration
BrowseItem.title
BrowseItem.subtitle
Definir dados do navegador de mídia
É possível fornecer uma lista de conteúdo de mídia para navegação chamando setBrowseContent
. Adicione o seguinte código ao arquivo js/receiver.js
abaixo da playerDataBinder
e no listener de eventos MEDIA_CHANGED
para definir os itens de navegação com o título "Próximo".
// 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);
});
Clicar em um item de navegação de mídia aciona o interceptador LOAD
. Adicione o código abaixo ao interceptador LOAD
para mapear o request.media.contentId
para request.media.entity
no 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 interface de navegação de mídia.
12. Como depurar apps receptores
O SDK do receptor do Google Cast oferece outra opção para que os desenvolvedores depurem facilmente os apps receptores usando a API CastDebugLogger e uma ferramenta CaC 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 de cima do arquivo e abaixo de playerManager
, adicione o seguinte código para recuperar a instância do 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 logger de depuração está ativado, uma sobreposição exibindo DEBUG MODE
é exibida no receptor.
Registrar eventos do player
Com o CastDebugLogger
, é fácil registrar eventos do player que são disparados pelo SDK do receptor CAF e usar diferentes níveis do logger 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 player for acionado ou uma mudança 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ê ache significativa. O CastDebugLogger
usa tags para filtrar os registros. O uso das tags é explicado em mais detalhes abaixo. O segundo parâmetro é a mensagem de registro.
Para mostrar os registros em ação, adicione registros ao seu 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
vai mostrar 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
exibirá apenas mensagens de registro de erro e de aviso.
A configuração loggerLevelByTags
é opcional. Se uma tag personalizada não estiver configurada para o nível do logger, todas as mensagens de registro serão mostradas na sobreposição de depuração.
Adicione o código a seguir abaixo do logger 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,
};
Sobreposição de depuração
O Cast Debug Logger oferece uma sobreposição de depuração no receptor para exibir as 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 nela.
Adicione o código a seguir para visualizar a sobreposição de depuração no 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();
}
});
13. Parabéns
Agora você já sabe como criar um app receptor da Web personalizado usando o SDK do receptor da Web do Google Cast.
Para ver mais detalhes, consulte o guia do desenvolvedor do Web Receiver.