Insertion d'annonces

ExoPlayer peut être utilisé à la fois pour l'insertion d'annonces côté client et côté serveur.

Insertion d'annonces côté client

Dans l'insertion d'annonces côté client, le lecteur bascule entre le chargement de contenus multimédias à partir de différentes URL lors de la transition entre la lecture de contenus et les annonces. Les informations sur les annonces sont chargées séparément du support, par exemple à partir d'un tag d'emplacement publicitaire XML VAST ou VMAP. Cela peut inclure les positions des repères d'annonce par rapport au début du contenu, les URI des médias publicitaires et les métadonnées, par exemple si une annonce donnée est ignorable.

Lorsque vous utilisez AdsMediaSource d'ExoPlayer pour l'insertion d'annonces côté client, le lecteur dispose d'informations sur les annonces à diffuser. Cela présente plusieurs avantages :

  • Le lecteur peut exposer les métadonnées et les fonctionnalités liées aux annonces à l'aide de son API.
  • Les composants d'interface utilisateur d'ExoPlayer peuvent afficher automatiquement des repères pour les positions des annonces et modifier leur comportement en fonction de la lecture de l'annonce.
  • En interne, le lecteur peut conserver un tampon cohérent entre les transitions entre les annonces et le contenu.

Dans cette configuration, le lecteur se charge de basculer entre les annonces et le contenu, ce qui signifie que les applications n'ont pas besoin de contrôler plusieurs lecteurs distincts en arrière-plan/au premier plan pour les annonces et le contenu.

Lorsque vous préparez des vidéos de contenu et des tags d'emplacement publicitaire pour une utilisation avec l'insertion d'annonces côté client, les annonces doivent idéalement être positionnées au niveau des échantillons de synchronisation (images clés) dans le contenu vidéo, afin que le lecteur puisse reprendre la lecture du contenu de manière fluide.

Prise en charge des annonces déclaratives

Vous pouvez spécifier un URI de tag d'emplacement publicitaire lors de la création d'une 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();

Pour permettre au lecteur de prendre en charge les éléments multimédias qui spécifient des tags d'annonce, vous devez créer et injecter un DefaultMediaSourceFactory configuré avec un AdsLoader.Provider et un AdViewProvider lors de la création du lecteur:

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

En interne, DefaultMediaSourceFactory encapsule la source multimédia de contenu dans un AdsMediaSource. AdsMediaSource obtiendra un AdsLoader à partir de AdsLoader.Provider et l'utilisera pour insérer des annonces comme défini par le tag d'emplacement publicitaire de l'élément multimédia.

PlayerView d'ExoPlayer implémente AdViewProvider. La bibliothèque IMA d'ExoPlayer fournit un AdsLoader facile à utiliser, comme décrit ci-dessous.

Playlists avec annonces

Lorsque vous lisez une playlist avec plusieurs éléments multimédias, le comportement par défaut consiste à demander le tag d'annonce et à stocker l'état de lecture de l'annonce une fois pour chaque combinaison d'ID multimédia, d'URI de contenu et d'URI de tag d'annonce. Cela signifie que les utilisateurs verront des annonces pour chaque élément multimédia avec des annonces ayant un ID multimédia ou un URI de contenu distinct, même si les URI de la balise d'annonce correspondent. Si un élément multimédia est répété, l'utilisateur ne verra les annonces correspondantes qu'une seule fois (l'état de lecture des annonces indique si elles ont été lues, elles sont donc ignorées après leur première occurrence).

Vous pouvez personnaliser ce comportement en transmettant un identifiant d'annonce opaque auquel l'état de lecture de l'annonce d'un élément multimédia donné est associé, en fonction de l'égalité des objets. Voici un exemple où l'état de lecture de l'annonce est associé uniquement à l'URI du tag d'emplacement publicitaire, plutôt qu'à la combinaison de l'ID multimédia et de l'URI du tag d'emplacement publicitaire, en transmettant l'URI du tag d'emplacement publicitaire comme identifiant des annonces. Les annonces ne seront donc chargées qu'une seule fois, et l'utilisateur ne verra pas d'annonces sur le deuxième élément lorsqu'il écoutera la playlist du début à la 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);

Bibliothèque IMA ExoPlayer

La bibliothèque IMA d'ExoPlayer fournit ImaAdsLoader, ce qui facilite l'intégration de l'insertion d'annonces côté client dans votre application. Elle encapsule les fonctionnalités du SDK IMA côté client pour prendre en charge l'insertion d'annonces VAST/VMAP. Pour savoir comment utiliser la bibliothèque, y compris pour gérer l'exécution en arrière-plan et la reprise de la lecture, consultez le fichier README.

L'application de démonstration utilise la bibliothèque IMA et inclut plusieurs exemples de tags publicitaires VAST/VMAP dans la liste d'exemples.

Considérations concernant l'interface utilisateur

Par défaut, PlayerView masque ses commandes de transport pendant la lecture des annonces, mais les applications peuvent activer ou désactiver ce comportement en appelant setControllerHideDuringAds. Le SDK IMA affiche des vues supplémentaires au-dessus du lecteur pendant la lecture d'une annonce (par exemple, un lien "Plus d'infos" et un bouton "Ignorer", le cas échéant).

Le SDK IMA peut indiquer si les annonces sont masquées par des vues fournies par l'application affichées au-dessus du lecteur. Les applications qui doivent superposer des vues essentielles pour contrôler la lecture doivent les enregistrer auprès du SDK IMA afin qu'elles puissent être omises des calculs de visibilité. Lorsque vous utilisez PlayerView comme AdViewProvider, il enregistre automatiquement ses superpositions de commandes. Les applications qui utilisent une UI de lecteur personnalisée doivent enregistrer des vues superposées en les renvoyant depuis AdViewProvider.getAdOverlayInfos.

Pour en savoir plus sur les vues de superposition, consultez Open Measurement dans le SDK IMA.

Annonces associées

Certains tags d'annonce contiennent des annonces associées supplémentaires qui peuvent être diffusées dans des "emplacements" dans l'interface utilisateur d'une application. Ces emplacements peuvent être transmis via ImaAdsLoader.Builder.setCompanionAdSlots(slots). Pour en savoir plus, consultez la section Ajouter des annonces associées.

Annonces autonomes

Le SDK IMA est conçu pour insérer des annonces dans des contenus multimédias et non pour diffuser des annonces autonomes. Par conséquent, la lecture d'annonces autonomes n'est pas prise en charge par la bibliothèque IMA. Pour ce cas d'utilisation, nous vous recommandons d'utiliser plutôt le SDK Google Mobile Ads.

Utiliser un SDK publicitaire tiers

Si vous devez charger des annonces via un SDK publicitaire tiers, il est utile de vérifier s'il fournit déjà une intégration ExoPlayer. Si ce n'est pas le cas, nous vous recommandons d'implémenter un AdsLoader personnalisé qui encapsule le SDK publicitaire tiers, car il offre les avantages de AdsMediaSource décrits ci-dessus. ImaAdsLoader sert d'exemple d'implémentation.

Vous pouvez également utiliser la compatibilité avec les playlists d'ExoPlayer pour créer une séquence d'annonces et de clips de contenu:

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

Insertion d'annonces côté serveur

Dans l'insertion d'annonces côté serveur (également appelée insertion dynamique d'annonces, ou DAI), le flux multimédia contient à la fois des annonces et du contenu. Un fichier manifeste DASH peut pointer vers du contenu et des segments d'annonces, éventuellement à des périodes distinctes. Pour le HLS, consultez la documentation Apple sur l'intégration d'annonces dans une playlist.

Lorsque vous utilisez l'insertion d'annonces côté serveur, le client peut être amené à résoudre l'URL multimédia de manière dynamique pour obtenir le flux assemblé, à afficher des superpositions d'annonces dans l'UI ou à signaler des événements à un SDK ou à un serveur d'annonces.

Le DefaultMediaSourceFactory d'ExoPlayer peut déléguer toutes ces tâches à un MediaSource d'insertion d'annonces côté serveur pour les URI à l'aide du schéma 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();

Bibliothèque IMA d'ExoPlayer

La bibliothèque IMA d'ExoPlayer fournit ImaServerSideAdInsertionMediaSource, ce qui facilite l'intégration aux flux d'annonces insérées côté serveur d'IMA dans votre application. Elle encapsule les fonctionnalités du SDK DAI IMA pour Android et intègre entièrement les métadonnées d'annonce fournies dans le lecteur. Par exemple, cela vous permet d'utiliser des méthodes telles que Player.isPlayingAd(), d'écouter les transitions entre le contenu et les annonces et de laisser le lecteur gérer la logique de lecture des annonces, comme le saut des annonces déjà lues.

Pour utiliser cette classe, vous devez configurer ImaServerSideAdInsertionMediaSource.AdsLoader et ImaServerSideAdInsertionMediaSource.Factory, puis les connecter au lecteur:

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

Chargez la clé d'élément IMA, ou l'ID de la source du contenu et l'ID vidéo, en créant une URL avec 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));

Enfin, libérez le chargeur d'annonces une fois qu'il n'est plus utilisé:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Considérations concernant l'interface utilisateur

Les mêmes considérations d'interface utilisateur que pour l'insertion d'annonces côté client s'appliquent également à l'insertion d'annonces côté serveur.

Annonces associées

Certains tags d'annonce contiennent des annonces associées supplémentaires qui peuvent être diffusées dans des "emplacements" dans l'interface utilisateur d'une application. Ces emplacements peuvent être transmis via ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots). Pour en savoir plus, consultez Ajouter des annonces associées.

Utiliser un SDK publicitaire tiers

Si vous devez charger des annonces à l'aide d'un SDK publicitaire tiers, il est utile de vérifier s'il fournit déjà une intégration ExoPlayer. Sinon, nous vous recommandons de fournir un MediaSource personnalisé qui accepte les URI avec le schéma ssai:// semblable à ImaServerSideAdInsertionMediaSource.

La logique de création de la structure d'annonce peut être déléguée à la ServerSideAdInsertionMediaSource à usage général, qui encapsule un MediaSource de flux et permet à l'utilisateur de définir et de mettre à jour le AdPlaybackState représentant les métadonnées de l'annonce.

Les flux d'annonces insérés côté serveur contiennent souvent des événements temporisés pour informer le lecteur des métadonnées des annonces. Pour en savoir plus sur les formats de métadonnées temporelles compatibles avec ExoPlayer, consultez la section Formats compatibles. Les implémentations MediaSource du SDK publicitaire personnalisé peuvent écouter les événements de métadonnées programmés du lecteur à l'aide de Player.Listener.onMetadata.