Integrar o SDK do Cast ao app de transmissão da Web

Este guia para desenvolvedores descreve como adicionar suporte ao Google Cast ao seu app de remetente da Web usando o SDK do Cast.

Terminologia

O dispositivo móvel ou o navegador é o remetente, que controla a reprodução. O dispositivo Google Cast é o receptor, que exibe o conteúdo na tela para reprodução.

O SDK do remetente da Web consiste em duas partes: a API Framework (cast.framework) e a API Base (chrome.cast). Em geral, você faz chamadas na API Framework mais simples e de nível mais alto, que são processadas pela API Base de nível inferior.

O framework do remetente se refere à API Framework, ao módulo e aos recursos associados que fornecem um wrapper para a funcionalidade de nível inferior. O app do remetente ou o app do Google Cast para Chrome se refere a um app da Web (HTML/JavaScript) executado em um navegador Chrome em um dispositivo do remetente. Um app receptor da Web se refere a um app HTML/JavaScript executado no Chromecast ou em um dispositivo com Google Cast.

O framework do remetente usa um design de callback assíncrono para informar o app remetente sobre eventos e fazer a transição entre vários estados do ciclo de vida do app do Google Cast.

Carregar a biblioteca

Para implementar os recursos do Google Cast, o app precisa saber o local do SDK do remetente da Web do Google Cast, conforme mostrado abaixo. Adicionamos o parâmetro de consulta de URL loadCastFramework para carregar a API Web Sender Framework. Todas as páginas do app precisam se referir à biblioteca da seguinte maneira:

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

Framework

O SDK do remetente da Web usa o namespace cast.framework.*. O namespace representa o seguinte:

  • Métodos ou funções que invocam operações na API
  • Listeners de eventos para funções de listener na API

O framework é composto por estes componentes principais:

  • O CastContext é um objeto Singleton que fornece informações sobre o estado atual do Google Cast e aciona eventos para mudanças de estado do estado e da sessão do Google Cast.
  • O objeto CastSession gerencia a sessão: ele fornece informações de estado e aciona eventos, como mudanças no volume do dispositivo, estado de silenciamento e metadados do app.
  • O elemento do botão Transmitir, que é um elemento personalizado HTML simples que amplia o botão HTML. Se o botão de transmissão fornecido não for suficiente, use o estado de transmissão para implementar um botão de transmissão.
  • O RemotePlayerController fornece a vinculação de dados para simplificar a implementação do player remoto.

Consulte a referência da API Google Cast Web Sender para uma descrição completa do namespace.

Botão "Transmitir"

O componente do botão de transmissão no app é totalmente gerenciado pelo framework. Isso inclui o gerenciamento de visibilidade e o processamento de eventos de clique.

<google-cast-launcher></google-cast-launcher>

Como alternativa, é possível criar o botão de forma programática:

document.createElement("google-cast-launcher");

Você pode aplicar qualquer estilo adicional, como tamanho ou posicionamento, ao elemento conforme necessário. Use o atributo --connected-color para escolher a cor do estado do Web Receiver conectado e --disconnected-color para o estado desconectado.

Inicialização

Depois de carregar a API do framework, o app vai chamar o manipulador window.__onGCastApiAvailable. Verifique se o app define esse manipulador no window antes de carregar a biblioteca do remetente.

Nesse gerenciador, você inicializa a interação do Google Cast chamando o método setOptions(options) do CastContext.

Exemplo:

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

Em seguida, inicialize a API da seguinte maneira:

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

Primeiro, o app recupera a instância Singleton do objeto CastContext fornecido pelo framework. Em seguida, ele usa setOptions(options) usando um objeto CastOptions para definir o applicationID.

Se você estiver usando o Media Receiver padrão, que não requer registro, use uma constante predefinida pelo SDK do remetente da Web, conforme mostrado abaixo, em vez de applicationID:

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

Controle de mídia

Depois que o CastContext for inicializado, o app poderá extrair o CastSession atual a qualquer momento usando getCurrentSession().

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

O CastSession pode ser usado para carregar mídia no dispositivo de transmissão conectado usando loadMedia(loadRequest). Primeiro, crie uma MediaInfo, usando contentId e contentType, além de qualquer outra informação relacionada ao conteúdo. Em seguida, crie um LoadRequest com ele, definindo todas as informações relevantes para a solicitação. Por fim, chame loadMedia(loadRequest) no CastSession.

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

O método loadMedia retorna uma promessa que pode ser usada para realizar as operações necessárias para um resultado positivo. Se a promessa for rejeitada, o argumento da função será um chrome.cast.ErrorCode.

É possível acessar as variáveis de estado do player em RemotePlayer. Todas as interações com o RemotePlayer, incluindo callbacks de eventos de mídia e comandos, são processadas com o RemotePlayerController.

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

O RemotePlayerController dá ao app o controle total de mídia de TOCAR, PAUSAR, PARAR e PROCURAR para a mídia carregada.

  • REPRODUZIR/PAUSAR: playerController.playOrPause();
  • STOP: playerController.stop();
  • SEEK: playerController.seek();

O RemotePlayer e o RemotePlayerController podem ser usados com frameworks de vinculação de dados, como Polymer ou Angular, para implementar um player remoto.

Confira um snippet de código para o Angular:

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

Status da mídia

Durante a reprodução de mídia, vários eventos ocorrem e podem ser capturados definindo listeners para vários eventos cast.framework.RemotePlayerEventType no objeto RemotePlayerController.

Para receber as informações de status da mídia, use o evento cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, que é acionado quando a reprodução muda e quando o CastSession.getMediaSession().media muda.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

Quando eventos como pausar, tocar, retomar ou procurar ocorrerem, o app precisará agir sobre eles e sincronizar entre si e o app do receptor da Web no dispositivo Cast. Consulte Atualizações de status para mais informações.

Como o gerenciamento de sessões funciona

O SDK do Google Cast apresenta o conceito de uma sessão do Google Cast, cuja criação combina as etapas de conexão a um dispositivo, inicialização (ou participação) de um app receptor da Web, conexão a esse app e inicialização de um canal de controle de mídia. Consulte o guia do ciclo de vida do aplicativo do receptor da Web para mais informações sobre as sessões do Google Cast e o ciclo de vida do receptor da Web.

As sessões são gerenciadas pela classe CastContext, que o app pode recuperar por meio de cast.framework.CastContext.getInstance(). As sessões individuais são representadas por subclasses da classe Session. Por exemplo, CastSession representa sessões com dispositivos de transmissão. Seu app pode acessar a sessão do Google Cast ativa no momento via CastContext.getCurrentSession().

Para monitorar o estado da sessão, adicione um listener ao CastContext para o tipo de evento CastContextEventType.SESSION_STATE_CHANGED.

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

Para desconexão, como quando o usuário clica no botão "Parar transmissão" na caixa de diálogo do Google Cast, adicione um listener para o tipo de evento RemotePlayerEventType.IS_CONNECTED_CHANGED no listener. No listener, verifique se RemotePlayer está desconectado. Se sim, atualize o estado do player local conforme necessário. Exemplo:

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

Embora o usuário possa controlar diretamente a interrupção da transmissão pelo botão de transmissão do framework, o remetente pode interromper a transmissão usando o objeto CastSession atual.

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

Transferência de stream

A preservação do estado da sessão é a base da transferência de streaming, em que os usuários podem mover streams de áudio e vídeo entre dispositivos usando comandos de voz, o app Google Home ou telas inteligentes. A mídia para de ser reproduzida em um dispositivo (a origem) e continua em outro (o destino). Qualquer dispositivo Cast com o firmware mais recente pode servir como origem ou destino em uma transferência de streaming.

Para receber o novo dispositivo de destino durante a transferência de streaming, chame CastSession#getCastDevice() quando o evento cast.framework.SessionState.SESSION_RESUMED for chamado.

Consulte Transferência de stream no Web Receiver para mais informações.