Inserção de anúncios

O ExoPlayer pode ser usado para inserção de anúncios do lado do cliente e do servidor.

Inserção de anúncios do lado do cliente

Na inserção de anúncios do lado do cliente, o player alterna entre o carregamento de mídia do URLs diferentes durante a transição entre a reprodução do conteúdo e dos anúncios. Informações sobre anúncios é carregado separadamente da mídia, como de um XML VAST ou VMAP. Isso pode incluir posições de inserção de anúncios relativas ao início do conteúdo, os URIs e metadados reais da mídia do anúncio, por exemplo, se um determinado anúncio (puláveis).

Ao usar o AdsMediaSource do ExoPlayer para inserção de anúncios do lado do cliente, o player tem informações sobre os anúncios que serão reproduzidos. Essa mudança gera vários benefícios:

  • O player pode expor metadados e funcionalidades relacionadas a anúncios usando sua API.
  • Os componentes de interface do ExoPlayer podem mostrar marcadores de posições de anúncios automaticamente. e mudam seu comportamento dependendo da exibição do anúncio.
  • Internamente, o jogador pode manter um buffer consistente nas transições anúncios e conteúdo.

Nesta configuração, o player cuida de alternar entre anúncios e conteúdo, o que significa que os aplicativos não precisam controlar vários players em segundo plano/primeiro plano para anúncios e conteúdo.

Ao preparar vídeos de conteúdo e tags de anúncio para uso com a inserção de anúncios do lado do cliente, os anúncios devem ser posicionados em amostras de sincronização (frames-chave) na conteúdo em vídeo para que o player possa retomar a reprodução do conteúdo sem problemas.

Suporte a anúncios declarativos

Um URI de tag de anúncio pode ser especificado ao criar um MediaItem:

Kotlin

val mediaItem =
  MediaItem.Builder()
    .setUri(videoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build())
    .build()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(videoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).build())
        .build();

Para ativar o suporte do player para itens de mídia que especificam tags de anúncio, é necessário criar e injetar um DefaultMediaSourceFactory configurado com um AdsLoader.Provider e um AdViewProvider ao criar o player:

Kotlin

val mediaSourceFactory: MediaSource.Factory =
  DefaultMediaSourceFactory(context).setLocalAdInsertionComponents(adsLoaderProvider, playerView)
val player = ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build()

Java

MediaSource.Factory mediaSourceFactory =
    new DefaultMediaSourceFactory(context)
        .setLocalAdInsertionComponents(adsLoaderProvider, /* adViewProvider= */ playerView);
ExoPlayer player =
    new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();

Internamente, o DefaultMediaSourceFactory agrupará a fonte de mídia do conteúdo em uma AdsMediaSource. O AdsMediaSource vai receber um AdsLoader do AdsLoader.Provider e use-o para inserir anúncios conforme definido pelo anúncio do item de mídia tag.

O PlayerView do ExoPlayer implementa AdViewProvider. O recurso de IMA do ExoPlayer fornece uma AdsLoader fácil de usar, conforme descrito abaixo.

Playlists com anúncios

Ao reproduzir uma playlist com vários itens de mídia, o comportamento padrão é para solicitar a tag de anúncio e armazenar o estado de reprodução do anúncio uma vez para cada ID de mídia, URI de conteúdo e URI de tag de anúncio. Isso significa que os usuários verão anúncios de cada item de mídia com anúncios que tenham um ID de mídia ou URI de conteúdo distinto, mesmo se os URIs da tag de anúncio serão correspondentes. Se um item de mídia for repetido, o usuário verá o anúncios correspondentes somente uma vez (o estado de reprodução do anúncio armazena se os anúncios foram reproduzidos, então eles são ignorados após a primeira ocorrência).

É possível personalizar esse comportamento transmitindo um identificador de anúncios opaco ao qual o estado de reprodução do anúncio para um determinado item de mídia está vinculado, com base no objeto equidade. Veja um exemplo em que o estado de reprodução do anúncio está vinculado à tag de anúncio URI, em vez da combinação do ID de mídia e URI da tag de anúncio, ao passando o URI da tag de anúncio como o identificador de anúncios. Por isso, os anúncios são carregados apenas uma vez, e o usuário não verá anúncios no segundo item ao reproduzir o playlist do início ao fim.

Kotlin

// Build the media items, passing the same ads identifier for both items,
// which means they share ad playback state so ads play only once.
val firstItem =
  MediaItem.Builder()
    .setUri(firstVideoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
    .build()
val secondItem =
  MediaItem.Builder()
    .setUri(secondVideoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
    .build()
player.addMediaItem(firstItem)
player.addMediaItem(secondItem)

Java

// Build the media items, passing the same ads identifier for both items,
// which means they share ad playback state so ads play only once.
MediaItem firstItem =
    new MediaItem.Builder()
        .setUri(firstVideoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
        .build();
MediaItem secondItem =
    new MediaItem.Builder()
        .setUri(secondVideoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
        .build();
player.addMediaItem(firstItem);
player.addMediaItem(secondItem);

Biblioteca do IMA do ExoPlayer

A biblioteca do ExoPlayer IMA (links em inglês) oferece ImaAdsLoader, facilitando integrar a inserção de anúncios do lado do cliente em seu aplicativo. Ele envolve a funcionalidade o SDK do IMA do lado do cliente para oferecer suporte à inserção de anúncios VAST/VMAP. Para instruções sobre como usar a biblioteca, incluindo como lidar com segundo plano e retomar a reprodução, consulte o arquivo README.

O aplicativo de demonstração usa a biblioteca do IMA e inclui várias amostras tags de anúncio VAST/VMAP na lista de amostras.

Considerações sobre a interface

PlayerView oculta os controles de transporte durante a reprodução de anúncios por padrão, mas os aplicativos podem alternar esse comportamento chamando setControllerHideDuringAds. O SDK do IMA mostrará visualizações adicionais o player durante a reprodução de um anúncio (por exemplo, um link "mais informações" e um botão ignorar, se aplicável).

O SDK do IMA pode informar se os anúncios estão ocultos por visualizações do aplicativo. renderizado sobre o player. Apps que precisam sobrepor visualizações que são essenciais para controlar a reprodução devem registrá-los no SDK do IMA para que elas podem ser omitidas dos cálculos de visibilidade. Ao usar PlayerView como AdViewProvider, ele vai registrar automaticamente as sobreposições de controle. Aplicativos que usam uma interface de player personalizada precisam registrar visualizações de sobreposição retornando-as de AdViewProvider.getAdOverlayInfos:

Para mais informações sobre visualizações de sobreposição, consulte Open Measurement no SDK do IMA.

Anúncios complementares

Algumas tags de anúncio contêm anúncios complementares adicionais que podem ser exibidos em "slots" em um interface do app. Esses slots podem ser transmitidos ImaAdsLoader.Builder.setCompanionAdSlots(slots): Para mais informações, consulte Como adicionar anúncios complementares.

Anúncios independentes

O SDK do IMA foi criado para inserir anúncios em conteúdo de mídia, não para reproduzir independentes. Por isso, a reprodução de anúncios independentes não é compatível. pela biblioteca do IMA. Recomendamos usar o SDK dos anúncios para dispositivos móveis do Google. para este caso de uso.

Como usar um SDK de anúncios de terceiros

Se você precisar carregar anúncios com um SDK de anúncios de terceiros, verifique se já fornece uma integração com o ExoPlayer. Caso contrário, implementar uma A abordagem recomendada é usar AdsLoader que envolva o SDK de anúncios de terceiros. já que oferece os benefícios do AdsMediaSource descritos acima. ImaAdsLoader atua como um exemplo de implementação.

Como alternativa, você pode usar o suporte a playlists do ExoPlayer para criar uma sequência de anúncios e clipes de conteúdo:

Kotlin

// A pre-roll ad.
val preRollAd = MediaItem.fromUri(preRollAdUri)
// The start of the content.
val contentStart =
  MediaItem.Builder()
    .setUri(contentUri)
    .setClippingConfiguration(ClippingConfiguration.Builder().setEndPositionMs(120000).build())
    .build()
// A mid-roll ad.
val midRollAd = MediaItem.fromUri(midRollAdUri)
// The rest of the content
val contentEnd =
  MediaItem.Builder()
    .setUri(contentUri)
    .setClippingConfiguration(ClippingConfiguration.Builder().setStartPositionMs(120000).build())
    .build()

// Build the playlist.
player.addMediaItem(preRollAd)
player.addMediaItem(contentStart)
player.addMediaItem(midRollAd)
player.addMediaItem(contentEnd)

Java

// A pre-roll ad.
MediaItem preRollAd = MediaItem.fromUri(preRollAdUri);
// The start of the content.
MediaItem contentStart =
    new MediaItem.Builder()
        .setUri(contentUri)
        .setClippingConfiguration(
            new ClippingConfiguration.Builder().setEndPositionMs(120_000).build())
        .build();
// A mid-roll ad.
MediaItem midRollAd = MediaItem.fromUri(midRollAdUri);
// The rest of the content
MediaItem contentEnd =
    new MediaItem.Builder()
        .setUri(contentUri)
        .setClippingConfiguration(
            new ClippingConfiguration.Builder().setStartPositionMs(120_000).build())
        .build();

// Build the playlist.
player.addMediaItem(preRollAd);
player.addMediaItem(contentStart);
player.addMediaItem(midRollAd);
player.addMediaItem(contentEnd);

Inserção de anúncios do lado do servidor

Na inserção de anúncios do lado do servidor (também chamada de inserção de anúncios dinâmicos, ou DAI), a o stream de mídia tem anúncios e conteúdo. Um manifesto DASH pode apontar para conteúdo e anúncios, possivelmente em períodos diferentes. Para HLS, consulte a documentação documentação sobre como incorporar anúncios a uma playlist.

Ao usar a inserção de anúncios do lado do servidor, o cliente pode precisar resolver a mídia de forma dinâmica para conseguir o fluxo integrado, pode ser necessário exibir sobreposições de anúncios na interface ou talvez precise relatar eventos para um SDK ou servidor de anúncios.

O DefaultMediaSourceFactory do ExoPlayer pode delegar todas essas tarefas a um Inserção de anúncios MediaSource do lado do servidor para URIs usando o esquema ssai://:

Kotlin

val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setServerSideAdInsertionMediaSourceFactory(ssaiFactory)
    )
    .build()

Java

Player player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setServerSideAdInsertionMediaSourceFactory(ssaiFactory))
        .build();

Biblioteca do IMA do ExoPlayer

A biblioteca do ExoPlayer IMA (links em inglês) oferece ImaServerSideAdInsertionMediaSource, o que facilita a integração com streams de anúncios inseridos pelo servidor do IMA nos seus app. Ele engloba a funcionalidade do SDK de DAI do IMA para Android e integra os metadados de anúncios fornecidos no player. Por exemplo, isso permite usar métodos como Player.isPlayingAd() e detectar transições de conteúdo e anúncio. e permitir que o player manipule a lógica de reprodução de anúncios, como pular anúncios já reproduzidos.

Para usar essa classe, você precisa configurar o ImaServerSideAdInsertionMediaSource.AdsLoader e o ImaServerSideAdInsertionMediaSource.Factory e conecte-os ao player:

Kotlin

// MediaSource.Factory to load the actual media stream.
val defaultMediaSourceFactory = DefaultMediaSourceFactory(context)
// AdsLoader that can be reused for multiple playbacks.
val adsLoader =
  ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build()
// MediaSource.Factory to create the ad sources for the current player.
val adsMediaSourceFactory =
  ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory)
// Configure DefaultMediaSourceFactory to create both IMA DAI sources and
// regular media sources. If you just play IMA DAI streams, you can also use
// adsMediaSourceFactory directly.
defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory)
// Set the MediaSource.Factory on the Player.
val player = ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build()
// Set the player on the AdsLoader
adsLoader.setPlayer(player)

Java

// MediaSource.Factory to load the actual media stream.
DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory(context);
// AdsLoader that can be reused for multiple playbacks.
ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader =
    new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build();
// MediaSource.Factory to create the ad sources for the current player.
ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory =
    new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory);
// Configure DefaultMediaSourceFactory to create both IMA DAI sources and
// regular media sources. If you just play IMA DAI streams, you can also use
// adsMediaSourceFactory directly.
defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory);
// Set the MediaSource.Factory on the Player.
Player player =
    new ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build();
// Set the player on the AdsLoader
adsLoader.setPlayer(player);

Carregue sua chave de recurso do IMA ou o ID da origem do conteúdo e do vídeo criando um URL com ImaServerSideAdInsertionUriBuilder:

Kotlin

val ssaiUri =
  ImaServerSideAdInsertionUriBuilder()
    .setAssetKey(assetKey)
    .setFormat(C.CONTENT_TYPE_HLS)
    .build()
player.setMediaItem(MediaItem.fromUri(ssaiUri))

Java

Uri ssaiUri =
    new ImaServerSideAdInsertionUriBuilder()
        .setAssetKey(assetKey)
        .setFormat(C.CONTENT_TYPE_HLS)
        .build();
player.setMediaItem(MediaItem.fromUri(ssaiUri));

Por fim, libere seu carregador de anúncios quando ele não for mais usado:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Considerações sobre a interface

As mesmas considerações de IU referentes à inserção de anúncios do lado do cliente se aplicam a a inserção de anúncios do lado do servidor.

Anúncios complementares

Algumas tags de anúncio contêm anúncios complementares adicionais que podem ser exibidos em "slots" em um interface do app. Esses slots podem ser transmitidos ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots): Para mais informações, consulte Adição de anúncios complementares.

Como usar um SDK de anúncios de terceiros

Se você precisar carregar anúncios usando um SDK de anúncios de terceiros, verifique se já fornece uma integração com o ExoPlayer. Caso contrário, é recomendado forneça um MediaSource personalizado que aceite URIs com o esquema ssai://. semelhantes a ImaServerSideAdInsertionMediaSource.

A lógica real de criação da estrutura do anúncio pode ser delegada à equipe geral a finalidade ServerSideAdInsertionMediaSource, que une um stream MediaSource; e permite que o usuário defina e atualize a AdPlaybackState que representa o anúncio. metadados.

Muitas vezes, os streams de anúncios inseridos pelo servidor contêm eventos com marcação de tempo para notificar o player. sobre metadados de anúncios. Consulte os formatos compatíveis para mais informações sobre quais formatos de metadados com marcação de tempo são compatíveis com o ExoPlayer. SDK de anúncios personalizados MediaSource implementações podem detectar eventos de metadados com marcação de tempo do player usando Player.Listener.onMetadata.