Use o SDK para DAI do IMA no Chromecast

Veja streams em direto registadas com a API Google Cloud Video Stitcher

Este guia demonstra como usar o SDK para DAI de IMA para recetores Web do CAF para pedir e ver uma transmissão em direto de um evento registado na API Google Cloud Video Stitcher e inserir uma pausa para anúncios durante a reprodução.

Este guia expande o exemplo básico da DAI de serviço completo, adicionando suporte para streams registadas na API Google Cloud Video Stitcher.

Certifique-se de que o formato de streaming é suportado pelos recetores Web do CAF antes de continuar.

Para obter informações sobre a integração com outras plataformas ou sobre a utilização dos SDKs do lado do cliente para IMA, consulte os SDKs para Anúncios Multimédia Interativos.

Contexto

Antes de usar este guia, familiarize-se com o protocolo Web Receiver do Chromecast Application Framework.

Este guia pressupõe um nível básico de familiaridade com os conceitos do recetor do CAF, como intercetores de mensagens, objetos MediaInformation e a utilização da ferramenta de comando e controlo do Cast para emular um remetente do CAF.

Componentes e arquitetura da app

A implementação da reprodução de streams em direto com a API Google Cloud Video Stitcher com o SDK IMA CAF DAI envolve dois componentes principais, conforme demonstrado neste guia:

  • VideoStitcherLiveStreamRequest: um objeto que define um pedido de stream para os servidores da Google. O pedido especifica uma instância da Cloud Video Stitcher API, um ID de configuração em direto e outros parâmetros opcionais.
  • StreamManager: Um objeto que processa a comunicação entre a stream de vídeo e o SDK para DAI do IMA, como o envio de pings de acompanhamento e o encaminhamento de eventos de stream para o publicador.

Pré-requisitos

Precisa das seguintes variáveis para o SDK para IMA:

  • ID da configuração em direto: este é o ID da configuração em direto que especificou quando criou a configuração em direto da API Video Stitcher.

    LIVE_CONFIG_ID

  • Localização: a região do Google Cloud onde a sua configuração em direto foi criada.

    LOCATION

  • Número do projeto: o número do projeto do Google Cloud que usa a API Video Stitcher.

    PROJECT_NUMBER

  • Token OAuth: o token OAuth de curta duração de uma conta de serviço com a função de utilizador do Video Stitcher. Leia mais sobre como criar credenciais de curta duração para contas de serviço.

    OAUTH_TOKEN

  • Network Code: código de rede do Google Ad Manager para pedir anúncios.

    NETWORK_CODE

  • Chave do recurso personalizado: chave do recurso personalizado do Google Ad Manager gerada durante o processo de criação de uma configuração para um evento de livestream com a API Video Stitcher.

    CUSTOM_ASSET_KEY

Precisa do seguinte para um recetor de transmissão personalizado:

  • Uma conta da Cast Developer Console com dispositivos de teste numa lista de autorizações.

  • Uma app Web Receiver alojada que esteja registada na sua Cast Developer Console e que possa ser modificada para alojar o código fornecido por este guia.

  • Uma app de envio configurada para usar a sua app de receção Web. Para efeitos deste exemplo, este guia usa a ferramenta de comando e controlo do Cast como remetente.

Prepare um remetente para transmitir dados de stream ao recetor

Primeiro, configure a sua app remetente para fazer um pedido de carregamento ao seu recetor Web, com os seguintes campos no objeto MediaInformation da sua plataforma.

Campo Índice
contentId Um identificador exclusivo deste item multimédia, conforme definido na documentação de referência do Cast. Este ID não deve ser reutilizado para vários itens na mesma fila de multimédia.

CONTENT_ID

contentUrl URL da stream de segurança opcional para reproduzir se a stream de DAI não for carregada.

BACKUP_STREAM_URL

contentType Tipo MIME opcional do URL da stream de segurança a ser reproduzido se a stream de DAI não for carregada.

BACKUP_STREAM_MIMETYPE

streamType A string literal ou a constante usada para este valor varia consoante a plataforma do remetente.

LIVE

customData

O campo customData contém um armazenamento de chave-valor de campos adicionais obrigatórios. Neste caso, customData contém os dados de stream da DAI que recolheu.

Campo Índice
liveConfigID LIVE_CONFIG_ID
region LOCATION
projectNumber PROJECT_NUMBER
oAuthToken OAUTH_TOKEN
networkCode NETWORK_CODE
customAssetKey CUSTOM_ASSET_KEY

Seguem-se alguns exemplos de código para ajudar a começar:

Web

Para configurar estes valores num remetente Web do Cast, primeiro crie um objeto MediaInfo com os dados necessários e, em seguida, faça um pedido load ao recetor Web.

// Create mediaInfo object
const mediaInfo = new chrome.cast.media.MediaInfo("CONTENT_ID");
mediaInfo.contentUrl = "BACKUP_STREAM_URL";
mediaInfo.contentType = "BACKUP_STREAM_MIMETYPE";
mediaInfo.streamType = chrome.cast.media.StreamType.LIVE;
mediaInfo.customData = {
liveConfigID: "LIVE_CONFIG_ID",
region: "LOCATION",
projectNumber: "PROJECT_NUMBER",
oAuthToken: "OAUTH_TOKEN",
networkCode: "NETWORK_CODE",
customAssetKey: "CUSTOM_ASSET_KEY"
};

// Make load request to cast web receiver
const castSession = cast.framework.CastContext.getInstance().getCurrentSession();
const request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  () => { console.log('Load succeed'); },
  (errorCode) => { console.log('Error code: ' + errorCode); });

Android

Para configurar estes valores num remetente Web do Cast, primeiro crie um objeto MediaInfo com os dados necessários e, em seguida, faça um pedido load ao recetor Web.

JSONObject customData = new JSONObject()
  .put("liveConfigID", "LIVE_CONFIG_ID")
  .put("region", "LOCATION")
  .put("projectNumber", "PROJECT_NUMBER")
  .put("oAuthToken", "OAUTH_TOKEN")
  .put("networkCode", "NETWORK_CODE")
  .put("customAssetKey", "CUSTOM_ASSET_KEY");

MediaInfo mediaInfo = MediaInfo.Builder("CONTENT_ID")
  .setContentUrl("BACKUP_STREAM_URL")
  .setContentType("BACKUP_STREAM_MIMETYPE")
  .setStreamType(MediaInfo.STREAM_TYPE_LIVE)
  .setCustomData(customData)
  .build();

RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());

iOS (Obj-C)

Para configurar estes valores num remetente Web do Cast, primeiro crie um objeto GCKMediaInformation com os dados necessários e, em seguida, faça um pedido load ao recetor Web.

NSURL url = [NSURL URLWithString:@"BACKUP_STREAM_URL"];
NSDictionary *customData = @{
  @"liveConfigID": @"LIVE_CONFIG_ID",
  @"region": @"LOCATION",
  @"projectNumber": @"PROJECT_NUMBER",
  @"oAuthToken": @"OAUTH_TOKEN",
  @"networkCode": @"NETWORK_CODE",
  @"customAssetKey": @"CUSTOM_ASSET_KEY"
};

GCKMediaInformationBuilder *mediaInfoBuilder =
  [[GCKMediaInformationBuilder alloc] initWithContentID: @"CONTENT_ID"];
mediaInfoBuilder.contentURL = url;
mediaInfoBuilder.contentType = @"BACKUP_STREAM_MIMETYPE";
mediaInfoBuilder.streamType = GCKMediaStreamTypeLive;
mediaInfoBuilder.customData = customData;
self.mediaInformation = [mediaInfoBuilder build];

GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation];
if (request != nil) {
  request.delegate = self;
}

iOS (Swift)

Para configurar estes valores num remetente Web do Cast, primeiro crie um objeto GCKMediaInformation com os dados necessários e, em seguida, faça um pedido load ao recetor Web.

let url = URL.init(string: "BACKUP_STREAM_URL")
guard let mediaURL = url else {
  print("invalid mediaURL")
  return
}

let customData = [
  "liveConfigID": "LIVE_CONFIG_ID",
  "region": "LOCATION",
  "projectNumber": "PROJECT_NUMBER",
  "oAuthToken": "OAUTH_TOKEN",
  "networkCode": "NETWORK_CODE",
  "customAssetKey": "CUSTOM_ASSET_KEY"
]

let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentId: "CONTENT_ID")
mediaInfoBuilder.contentURL = mediaUrl
mediaInfoBuilder.contentType = "BACKUP_STREAM_MIMETYPE"
mediaInfoBuilder.streamType = GCKMediaStreamType.Live
mediaInfoBuilder.customData = customData
mediaInformation = mediaInfoBuilder.build()

guard let mediaInfo = mediaInformation else {
  print("invalid mediaInformation")
  return
}

if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) {
  request.delegate = self
}

Ferramenta CAC

Para configurar estes valores na ferramenta de comando e controlo do Cast, clique no separador Carregar conteúdo multimédia e defina o tipo de pedido de carregamento personalizado como LOAD. Em seguida, substitua os dados JSON na área de texto por este JSON:

{
  "media": {
    "contentId": "CONTENT_ID",
    "contentUrl": "BACKUP_STREAM_URL",
    "contentType": "BACKUP_STREAM_MIMETYPE",
    "streamType": "LIVE",
    "customData": {
      "liveConfigID": "LIVE_CONFIG_ID",
      "region": "LOCATION",
      "projectNumber": "PROJECT_NUMBER",
      "oAuthToken": "OAUTH_TOKEN",
      "networkCode": "NETWORK_CODE",
      "customAssetKey": "CUSTOM_ASSET_KEY"
    }
  }
}

Este pedido de carregamento personalizado pode ser enviado para o recetor para testar os restantes passos.

Crie um recetor Web CAF personalizado

Crie um recetor Web personalizado, conforme descrito no guia do recetor Web personalizado do SDK CAF.

O código do recetor deve ter o seguinte aspeto:

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js">
  </script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance()
    castContext.start();
  </script>
</body>
</html>

Importe o SDK IMA DAI e obtenha o gestor do leitor

Adicione uma etiqueta de script para importar o SDK IMA DAI para CAF para o seu recetor Web, imediatamente após o script de carregamento do CAF. Em seguida, na etiqueta de script que se segue, armazene o contexto do recetor e o gestor do leitor como constantes antes de iniciar o recetor.

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();

    castContext.start();
  </script>
</body>
</html>

Inicialize o gestor de streams do IMA

Inicialize o gestor de streams do IMA.

<html>
<head>
  <script type="text/javascript"
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    castContext.start();
  </script>
</body>
</html>

Crie o interceptor de carregamento do Gestor de streams

Antes de os itens multimédia serem transmitidos para o CAF, crie o pedido de stream num intercetor de mensagens LOAD.

    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    /**
     * Creates a livestream request object for the Video Stitcher API.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => { /* ... */};

    /**
     * Initates a DAI stream request for the final stream manifest.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {Promise<LoadRequestData>} a promise that resolves to an updated castRequest, containing the DAI stream manifest
     */
    const createDAICastRequest = (castRequest) => {
        return streamManager.requestStream(castRequest, createStreamRequest(castRequest))
          .then((castRequestWithStreamData) => {
            console.log('Successfully made DAI stream request.');
            return castRequestWithStreamData;
          })
          .catch((error) => {
            console.log('Failed to make DAI stream request.');
            // CAF will automatically fallback to the content URL
            // that it can read from the castRequest object.
            return castRequest;
          });
    };

    playerManager.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, createDAICastRequest);

    castContext.start();

Crie o pedido de stream

Conclua a função createStreamRequest para criar um pedido de stream em direto da API Video Stitcher com base no pedido de carregamento do CAF.

    /**
     * Creates a livestream request object for the Video Stitcher API.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => {
      const streamRequest = new google.ima.cast.dai.api.VideoStitcherLiveStreamRequest();
      const customData = castRequest.media.customData;

      streamRequest.liveStreamEventId = customData.liveConfigID;
      streamRequest.region = customData.region;
      streamRequest.projectNumber = customData.projectNumber;
      streamRequest.oAuthToken = customData.oAuthToken;
      streamRequest.networkCode = customData.networkCode;
      streamRequest.customAssetKey = customData.customAssetKey;

      return streamRequest;
    };

(Opcional) Adicione opções de sessão de streaming

Personalize o seu pedido de stream adicionando opções de sessão para substituir a configuração predefinida da API Cloud Video Stitcher através de VideoStitcherLiveStreamRequest.videoStitcherSessionOptions. Se fornecer uma opção não reconhecida, a API Cloud Video Stitcher responde com um erro HTTP 400. Consulte o guia de resolução de problemas para obter assistência.

Por exemplo, pode substituir as opções do manifesto com o seguinte fragmento do código, que pede dois manifestos de streams com representações ordenadas da taxa de bits mais baixa para a mais alta.

...

// The following session options are examples. Use session options
// that are compatible with your video stream.
streamRequest.videoStitcherSessionOptions = {
  "manifestOptions": {
    "bitrateOrder": "ascending"
  }
};

streamManager.requestStream(streamRequest);