ExoPlayer peut être utilisé 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 passe du chargement de contenus à partir de différentes URL lorsqu'il passe de la lecture de contenus à celle d'annonces. Les informations sur les annonces sont chargées séparément du contenu multimédia, par exemple à partir d'un tag d'annonce XML VAST ou VMAP. Cela peut inclure les positions des repères publicitaires par rapport au début du contenu, les URI des supports publicitaires et les métadonnées, par exemple pour savoir si une annonce donnée peut être ignorée.
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 des métadonnées et des fonctionnalités liées aux annonces à l'aide de son API.
- Les composants d'UI ExoPlayer peuvent afficher automatiquement des repères pour les positions des annonces et modifier leur comportement selon que l'annonce est en cours de lecture ou non.
- En interne, le lecteur peut conserver un tampon cohérent lors des transitions entre les annonces et le contenu.
Dans cette configuration, le lecteur se charge de passer des annonces au contenu, ce qui signifie que les applications n'ont pas besoin de contrôler plusieurs lecteurs d'arrière-plan/de premier plan distincts pour les annonces et le contenu.
Lorsque vous préparez des vidéos de contenu et des tags d'emplacement publicitaire pour l'insertion d'annonces côté client, les annonces doivent idéalement être positionnées au niveau des exemples de synchronisation (images clés) de la vidéo de contenu afin que le lecteur puisse reprendre la lecture du contenu de manière fluide.
Compatibilité avec les annonces déclaratives
Un URI de tag d'emplacement publicitaire peut être spécifié lors de la création d'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();
Pour activer la prise en charge des éléments multimédias qui spécifient des tags d'annonce, il est nécessaire de créer et d'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 encapsulera la source de contenu multimédia dans un AdsMediaSource. Le AdsMediaSource obtient un AdsLoader à partir de AdsLoader.Provider et l'utilise pour insérer des annonces telles que définies par le tag d'annonce de l'élément multimédia.
PlayerView d'ExoPlayer implémente AdViewProvider. La bibliothèque ExoPlayer IMA fournit un AdsLoader facile à utiliser, comme décrit ci-dessous.
Playlists avec annonces
Lorsque vous lisez une playlist comportant plusieurs éléments multimédias, le comportement par défaut consiste à demander le tag d'emplacement publicitaire et à stocker l'état de lecture de l'annonce une fois pour chaque combinaison d'ID de contenu multimédia, d'URI de contenu et d'URI de tag d'emplacement publicitaire. Cela signifie que les utilisateurs verront des annonces pour chaque élément multimédia avec des annonces qui possède un ID multimédia ou un URI de contenu distincts, même si les URI des tags 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 des annonces ont été diffusées, de sorte qu'elles sont ignorées après leur première diffusion).
Il est possible de personnaliser ce comportement en transmettant un identifiant publicitaire opaque auquel l'état de lecture des annonces pour un élément multimédia donné est associé, en fonction de l'égalité des objets. Voici un exemple où l'état de lecture des annonces est associé uniquement à l'URI du tag d'emplacement publicitaire, plutôt qu'à la combinaison de l'ID du contenu multimédia et de l'URI du tag d'emplacement publicitaire, en transmettant l'URI du tag d'emplacement publicitaire comme identifiant des annonces. L'effet est que les annonces ne se chargeront qu'une seule fois et que l'utilisateur ne verra pas d'annonces sur le deuxième élément lorsqu'il lira 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);
Insertion d'annonces côté client guidée par le serveur
ExoPlayer est fourni avec HlsInterstitialsAdsLoader, qui permet d'insérer automatiquement côté client les annonces définies dans la playlist HLS. Consultez la section sur HlsInterstitialsAdsLoader sur la page HLS.
Bibliothèque ExoPlayer IMA
La bibliothèque ExoPlayer IMA fournit ImaAdsLoader, ce qui facilite l'intégration de l'insertion d'annonces côté client dans votre application. Elle encapsule la fonctionnalité du SDK IMA côté client pour permettre l'insertion d'annonces VAST/VMAP. Pour obtenir des instructions sur l'utilisation de la bibliothèque, y compris sur la façon de gérer la mise en arrière-plan et la reprise de la lecture, veuillez consulter le fichier README.
L'application de démonstration utilise la bibliothèque IMA et inclut plusieurs exemples de tags d'emplacement publicitaire VAST/VMAP dans la liste d'exemples.
Considérations relatives à l'UI
PlayerView masque ses commandes de transport pendant la lecture des annonces par défaut, mais les applications peuvent activer ou désactiver ce comportement en appelant setControllerHideDuringAds. Le SDK IMA affichera 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 des annonces sont masquées par des vues fournies par l'application et affichées au-dessus du lecteur. Les applications qui doivent superposer des vues essentielles au contrôle de la lecture doivent les enregistrer auprès du SDK IMA afin qu'elles puissent être exclues des calculs de la visibilité. Lorsque vous utilisez PlayerView comme AdViewProvider, il enregistre automatiquement ses calques de contrôle. Les applications qui utilisent une UI de lecteur personnalisée doivent enregistrer les vues de superposition en les renvoyant à partir de AdViewProvider.getAdOverlayInfos.
Pour en savoir plus sur les vues superposées, 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" de l'interface utilisateur d'une application. Ces emplacements peuvent être transmis via ImaAdsLoader.Builder.setCompanionAdSlots(slots). Pour en savoir plus, consultez Ajouter des annonces associées.
Annonces autonomes
Le SDK IMA est conçu pour insérer des annonces dans du contenu multimédia, et non pour lire des annonces autonomes. Par conséquent, la lecture d'annonces autonomes n'est pas prise en charge par la bibliothèque IMA. Nous vous recommandons d'utiliser plutôt le SDK Google Mobile Ads pour ce cas d'utilisation.
Utiliser un SDK d'annonces tiers
Si vous devez charger des annonces via un SDK publicitaire tiers, vérifiez s'il fournit déjà une intégration ExoPlayer. Sinon, l'approche recommandée consiste à implémenter un AdsLoader personnalisé qui encapsule le SDK d'annonces tiers, car il offre les avantages de AdsMediaSource décrits ci-dessus.
ImaAdsLoader sert d'exemple d'implémentation.
Vous pouvez également utiliser la prise en charge des playlists d'ExoPlayer pour créer une séquence d'annonces et d'extraits de contenu :
Kotlin
// A pre-roll ad. val preRollAd = MediaItem.fromUri(preRollAdUri) // The start of the content. val contentStart = MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration(MediaItem.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(MediaItem.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 MediaItem.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 MediaItem.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 des segments de contenu et d'annonces, éventuellement dans des périodes distinctes. Pour 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 avoir besoin de résoudre l'URL du contenu multimédia de manière dynamique pour obtenir le flux assemblé, d'afficher des annonces superposées dans l'UI ou de signaler des événements à un SDK d'annonces ou à un serveur publicitaire.
Le DefaultMediaSourceFactory d'ExoPlayer peut déléguer toutes ces tâches à un MediaSource d'insertion d'annonces côté serveur pour les URI utilisant le 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 ExoPlayer IMA
La bibliothèque ExoPlayer IMA 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 IMA DAI pour Android et intègre entièrement les métadonnées d'annonce fournies au lecteur. Par exemple, cela vous permet d'utiliser des méthodes telles que Player.isPlayingAd(), d'écouter les transitions entre les contenus et les annonces, et de laisser le lecteur gérer la logique de lecture des annonces, comme ignorer les 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 votre clé d'asset IMA, ou l'ID de la source de 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 votre chargeur d'annonces une fois qu'il n'est plus utilisé :
Kotlin
adsLoader.release()
Java
adsLoader.release();
Considérations relatives à l'UI
Les mêmes considérations concernant l'UI 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" de 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 d'annonces tiers
Si vous devez charger des annonces à l'aide d'un SDK d'annonces tiers, vérifiez s'il fournit déjà une intégration ExoPlayer. Sinon, il est recommandé de fournir un MediaSource personnalisé qui accepte les URI avec le schéma ssai://, comme ImaServerSideAdInsertionMediaSource.
La logique de création de la structure publicitaire peut être déléguée à ServerSideAdInsertionMediaSource à usage général, qui encapsule un flux MediaSource et permet à l'utilisateur de définir et de mettre à jour AdPlaybackState représentant les métadonnées de l'annonce.
Souvent, les flux d'annonces insérées côté serveur contiennent des événements temporels 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 page Formats compatibles. Les implémentations du SDK d'annonces personnalisées MediaSource peuvent écouter les événements de métadonnées temporelles du lecteur à l'aide de Player.Listener.onMetadata.