Inserción de anuncios

ExoPlayer se puede usar para la inserción de anuncios del cliente y del servidor.

Inserción de anuncios del cliente

En la inserción de anuncios del cliente, el reproductor cambia entre cargar contenido multimedia desde diferentes URL a medida que pasa del contenido de reproducción a los anuncios. Información acerca de los anuncios se carga de forma independiente del contenido multimedia, como desde un archivo XML VAST o VMAP. Puede incluir posiciones de inserciones de anuncios relacionadas con el inicio de la contenido, los URI de medios reales del anuncio y los metadatos (por ejemplo, si un anuncio determinado se que se pueden omitir.

Cuando se usa AdsMediaSource de ExoPlayer para la inserción de anuncios del cliente, el reproductor contiene información sobre los anuncios que se reproducirán. Esto tiene varios beneficios, como los siguientes:

  • El reproductor puede exponer metadatos y funciones relacionadas con los anuncios mediante su API.
  • Los componentes de IU de ExoPlayer pueden mostrar marcadores para las posiciones de anuncios automáticamente, y cambiar su comportamiento según si el anuncio se está reproduciendo.
  • Internamente, el reproductor puede mantener un búfer coherente entre las transiciones anuncios y contenido.

En esta configuración, el reproductor se ocupa de alternar entre anuncios y contenido, significa que las apps no tienen que encargarse de controlar varias reproductores en segundo plano y en primer plano para anuncios y contenido.

Cuando prepares videos de contenido y etiquetas de anuncios para usar en la inserción de anuncios del cliente, los anuncios deben ubicarse idealmente en muestras de sincronización (fotogramas clave) en la video de contenido para que el reproductor pueda reanudar la reproducción de contenido sin problemas.

Compatibilidad de anuncios declarativa

Se puede especificar un URI de etiqueta de anuncio cuando se compila un 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 habilitar la compatibilidad con el reproductor para elementos multimedia que especifican etiquetas de anuncios, es necesario compilar e insertar un DefaultMediaSourceFactory configurado con un AdsLoader.Provider y AdViewProvider cuando se crea el reproductor:

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();

De forma interna, DefaultMediaSourceFactory unirá la fuente multimedia del contenido en una AdsMediaSource AdsMediaSource obtendrá un AdsLoader de la AdsLoader.Provider y usarla para insertar anuncios según lo definido por el anuncio del elemento multimedia etiqueta.

PlayerView de ExoPlayer implementa AdViewProvider. La IMA de ExoPlayer proporciona un AdsLoader fácil de usar, como se describe a continuación.

Playlists con anuncios

Cuando se reproduce una playlist con varios elementos multimedia, el comportamiento predeterminado es el siguiente: para solicitar la etiqueta de anuncio y almacenar el estado de reproducción del anuncio una vez para cada ID de medios la combinación de URI de contenido y URI de etiqueta de anuncio. Esto significa que los usuarios verán anuncios de todos los elementos multimedia con anuncios que tienen un ID de medios o URI de contenido distinto, incluso si cuando los URI de la etiqueta del anuncio coincidan. Si un elemento multimedia se repite, el usuario verá el anuncios correspondientes solo una vez (el estado de reproducción del anuncio almacena si los anuncios se han se reproducen, por lo que se omiten tras la primera repetición).

Es posible personalizar este comportamiento pasando un identificador de anuncios opacos. con el que se vincula el estado de reproducción de un anuncio para un elemento multimedia determinado, según igualdad. A continuación, se muestra un ejemplo en el que el estado de reproducción de un anuncio se vincula con la etiqueta de anuncio Solo el URI, en lugar de la combinación del ID de medios y el URI de la etiqueta de anuncio, mediante y pasar el URI de la etiqueta de anuncio como identificador de anuncios. Como resultado, los anuncios se cargan solo una vez y el usuario no verá anuncios en el segundo elemento mientras reproduce el playlist de principio a fin.

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 de IMA de ExoPlayer

La biblioteca de IMA de ExoPlayer proporciona ImaAdsLoader, lo que facilita la Integra en tu app la inserción de anuncios del cliente. Incluye la funcionalidad de el SDK de IMA del cliente para admitir la inserción de anuncios VAST/VMAP Para instrucciones para usar la biblioteca, incluido cómo manejar el fondo y reanudar la reproducción, consulta el archivo README.

La aplicación de demostración usa la biblioteca de IMA y también incluye varias Etiquetas de anuncios VAST/VMAP en la lista de muestra.

Consideraciones sobre la IU

PlayerView oculta sus controles de transporte durante la reproducción de anuncios: de forma predeterminada, pero las apps pueden activar o desactivar este comportamiento llamando setControllerHideDuringAds El SDK de IMA mostrará vistas adicionales además de el reproductor mientras se reproduce un anuncio (por ejemplo, un vínculo “más información” y un botón para omitir, si corresponde).

El SDK de IMA puede informar si las vistas proporcionadas por la aplicación oscurecen los anuncios. se renderiza sobre el reproductor. Las aplicaciones que necesitan superponer vistas que son esencial para controlar la reproducción, deben registrarlas con el SDK de IMA de modo que se pueden omitir en los cálculos de visibilidad. Cuando uses PlayerView como AdViewProvider, registrará automáticamente sus superposiciones de control. Aplicaciones que usan una IU de reproductor personalizada deben registrar vistas superpuestas mostrándolas desde AdViewProvider.getAdOverlayInfos

Para obtener más información sobre las vistas superpuestas, consulta Open Measurement en el SDK de IMA.

Anuncios complementarios

Algunas etiquetas de anuncios contienen anuncios complementarios adicionales que se pueden mostrar en "espacios" en una en la IU de la app. Estas ranuras se pueden pasar ImaAdsLoader.Builder.setCompanionAdSlots(slots) Para obtener más información, consulta Cómo agregar anuncios complementarios

Anuncios independientes

El SDK de IMA está diseñado para insertar anuncios en el contenido multimedia, no para reproducirlos anuncios independientes por sí mismos. Por lo tanto, no se admite la reproducción de anuncios independientes. la biblioteca de IMA. Recomendamos utilizar el SDK de anuncios de Google para dispositivos móviles en su lugar para este caso de uso.

Usa un SDK de anuncios de terceros

Si necesita cargar anuncios con un SDK de anuncios de terceros, ya proporciona una integración de ExoPlayer. De lo contrario, implementar una campaña Se recomienda usar una AdsLoader que incluya el SDK de anuncios de terceros. ya que proporciona los beneficios de AdsMediaSource descritos anteriormente. ImaAdsLoader actúa como ejemplo de implementación.

De manera alternativa, puedes usar la compatibilidad con playlists de ExoPlayer para crear una secuencia de anuncios y clips de contenido:

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);

Inserción de anuncios del servidor

En la inserción de anuncios del servidor (también llamada inserción de anuncios dinámicos o DAI), el que incluye tanto anuncios como contenido. Un manifiesto de DASH puede apuntar a ambos contenido y segmentos de anuncios, posiblemente en períodos separados. Para HLS, consulta el Consulta la documentación sobre cómo incorporar anuncios en una playlist.

Cuando se usa la inserción de anuncios del servidor, es posible que el cliente deba resolver el problema URL de forma dinámica para obtener la transmisión unida, es posible que deba mostrar anuncios superpuestos en la IU, o tal vez debas informar eventos a un SDK de anuncios o a un servidor de anuncios.

El DefaultMediaSourceFactory de ExoPlayer puede delegar todas estas tareas a un Inserción de anuncios del servidor MediaSource para URI que usan el 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 de IMA de ExoPlayer

La biblioteca de IMA de ExoPlayer proporciona ImaServerSideAdInsertionMediaSource, lo que facilita la integración con los flujos de anuncios insertados del servidor de IMA en su . Incluye la funcionalidad del SDK de IMA de DAI para Android y Integra en el reproductor los metadatos de anuncios proporcionados. Por ejemplo, esto permite que uses métodos como Player.isPlayingAd(), que escuches transiciones y permite que el reproductor controle la lógica de reproducción de anuncios, como omitir los anuncios que ya se reprodujeron.

Para usar esta clase, debes configurar la clase ImaServerSideAdInsertionMediaSource.AdsLoader y las ImaServerSideAdInsertionMediaSource.Factory y conéctalas al reproductor de la siguiente manera:

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);

Para cargar su clave de recurso de IMA, o ID de fuente del contenido y de video, cree una URL con 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 último, suelta el cargador de anuncios cuando ya no se utilice:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Consideraciones sobre la IU

Se aplican las mismas consideraciones de la IU que para la inserción de anuncios del cliente: la inserción de anuncios del servidor.

Anuncios complementarios

Algunas etiquetas de anuncios contienen anuncios complementarios adicionales que se pueden mostrar en "espacios" en una en la IU de la app. Estas ranuras se pueden pasar ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots) Para obtener más información, consulta Cómo agregar anuncios complementarios.

Usa un SDK de anuncios de terceros

Si necesita cargar anuncios con un SDK de anuncios de terceros, ya proporciona una integración de ExoPlayer. De lo contrario, se recomienda Proporciona un MediaSource personalizado que acepte URIs con el esquema ssai://. similar a ImaServerSideAdInsertionMediaSource.

La lógica real de la creación de la estructura del anuncio se puede delegar al propósito ServerSideAdInsertionMediaSource, que une un flujo MediaSource y permite que el usuario establezca y actualice el objeto AdPlaybackState que representa el anuncio metadatos.

A menudo, las transmisiones de anuncios insertadas del servidor contienen eventos cronometrados para notificar al reproductor. sobre los metadatos de anuncios. Consulta los formatos compatibles para obtener información sobre Los formatos de metadatos temporizados son compatibles con ExoPlayer. SDK de anuncios personalizados MediaSource las implementaciones pueden escuchar eventos de metadatos temporizados desde el reproductor usando Player.Listener.onMetadata