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 bascule entre le chargement de contenu multimédia à partir de différentes URL lorsqu'il passe de la lecture du contenu aux 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 du repère de l'annonce par rapport au début du contenu, les URI réels de l'annonce et des métadonnées, par exemple si une annonce donnée est désactivable ou non.
Lorsque vous utilisez le AdsMediaSource
d'ExoPlayer pour insérer des annonces côté client, le lecteur dispose d'informations sur les annonces à lire. Cela présente plusieurs avantages :
- Le lecteur peut présenter des métadonnées et des fonctionnalités liées aux annonces à l'aide de son API.
- Les composants d'UI d'ExoPlayer peuvent afficher automatiquement des repères pour la position des annonces et modifier leur comportement selon que l'annonce est diffusée ou non.
- En interne, le lecteur peut conserver un tampon cohérent entre les transitions entre les annonces et le contenu.
Dans cette configuration, le lecteur bascule entre les annonces et le 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.
Lors de la préparation des vidéos de contenu et des tags d'emplacement publicitaire à utiliser 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 la vidéo de contenu afin que le lecteur puisse reprendre la lecture du contenu sans difficulté.
Compatibilité avec les annonces déclaratives
Vous pouvez spécifier un URI de tag d'emplacement publicitaire 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 compatibilité du lecteur avec les éléments multimédias qui spécifient des tags d'emplacement publicitaire, vous devez créer et injecter un DefaultMediaSourceFactory
configuré avec AdsLoader.Provider
et 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
obtient un AdsLoader
à partir de AdsLoader.Provider
et l'utilise pour insérer des annonces comme défini par le tag d'emplacement publicitaire de l'élément multimédia.
Le 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
Lors de la lecture d'une playlist avec 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 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 ayant un ID média ou un URI de contenu distincts, même si les URI des tags d'emplacement publicitaire 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 stocke si des annonces ont été lues, elles seront donc ignorées après leur première occurrence).
Il est possible de personnaliser ce comportement en transmettant un identifiant d'annonce opaque auquel l'état de lecture d'un élément multimédia donné est associé, en fonction de l'égalité des objets. Dans l'exemple ci-dessous, l'état de lecture d'une annonce n'est associé qu'à l'URI du tag d'emplacement publicitaire, et non à la combinaison de l'ID média et de l'URI du tag d'emplacement publicitaire, en transmettant l'URI du tag d'emplacement publicitaire en tant qu'identifiant de l'annonce. Il en résulte que les annonces ne se chargent qu'une seule fois et que l'utilisateur ne verra aucune annonce sur le deuxième élément lors de la lecture de 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 d'ExoPlayer
La bibliothèque IMA d'ExoPlayer fournit ImaAdsLoader
, ce qui facilite l'intégration d'annonces côté client dans votre application. Elle intègre les fonctionnalités 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 gestion de la mise en arrière-plan et de 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 d'emplacement publicitaire VAST/VMAP dans la liste d'exemples.
Remarques sur l'interface utilisateur
Par défaut, PlayerView
masque les 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 en haut 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 les vues fournies par l'application qui s'affichent au-dessus du lecteur. Les applications qui doivent superposer des vues essentielles pour le contrôle de la lecture doivent les enregistrer avec le SDK IMA pour pouvoir les omettre dans les 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 les vues en superposition en les renvoyant à partir de AdViewProvider.getAdOverlayInfos
.
Pour en savoir plus sur les vues en superposition, consultez Open Measurement dans le SDK IMA.
Annonces associées
Certains tags d'emplacement publicitaire contiennent des annonces associées supplémentaires qui peuvent s'afficher dans des "espaces publicitaires" au sein d'une interface utilisateur d'application. Ces emplacements peuvent être transmis via ImaAdsLoader.Builder.setCompanionAdSlots(slots)
. Pour plus d'informations, consultez la section 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 diffuser des annonces autonomes. La lecture d'annonces autonomes n'est donc pas compatible avec la bibliothèque IMA. Nous vous recommandons plutôt d'utiliser le SDK Google Mobile Ads pour ce cas d'utilisation.
Utiliser un SDK publicitaire tiers
Si vous devez charger des annonces via un SDK publicitaire tiers, vérifiez s'il propose 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é 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(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'annonce), le flux multimédia contient à la fois des annonces et du contenu. Un fichier manifeste DASH peut renvoyer à la fois vers des segments de contenu et d'annonces, éventuellement dans des périodes distinctes. Pour le protocole HLS, consultez la documentation d'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 multimédia de manière dynamique pour obtenir le flux assemblé, d'afficher des superpositions d'annonces dans l'interface utilisateur ou de signaler des événements à un SDK publicitaire ou à un ad server.
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 IMA d'ExoPlayer
La bibliothèque IMA d'ExoPlayer fournit ImaServerSideAdInsertionMediaSource
, ce qui facilite l'intégration dans votre application aux flux d'annonces insérés côté serveur d'IMA. Elle englobe les fonctionnalités du SDK IMA DAI pour Android et intègre entièrement les métadonnées d'annonces fournies dans le lecteur. Par exemple, cela vous permet d'utiliser des méthodes telles que Player.isPlayingAd()
, d'écouter les transitions de contenu/annonce 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'élément IMA (ou ID de source de contenu et votre 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 lorsqu'il n'est plus utilisé:
Kotlin
adsLoader.release()
Java
adsLoader.release();
Remarques sur l'interface utilisateur
Les mêmes considérations relatives à l'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'emplacement publicitaire contiennent des annonces associées supplémentaires qui peuvent s'afficher dans des "espaces publicitaires" au sein d'une interface utilisateur d'application. Ces emplacements peuvent être transmis via ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots)
.
Pour plus d'informations, consultez la section Ajouter des annonces associées.
Utiliser un SDK publicitaire tiers
Si vous devez charger des annonces à l'aide d'un SDK publicitaire tiers, vérifiez s'il propose déjà une intégration ExoPlayer. Si ce n'est pas le cas, il est recommandé de fournir un MediaSource
personnalisé qui accepte les URI avec un schéma ssai://
semblable à ImaServerSideAdInsertionMediaSource
.
La logique de création de la structure d'annonce peut être déléguée à l'ServerSideAdInsertionMediaSource
à usage général, qui encapsule un flux MediaSource
et permet à l'utilisateur de définir et de mettre à jour l'AdPlaybackState
représentant les métadonnées de l'annonce.
Souvent, les flux d'annonces insérés côté serveur contiennent des événements programmés pour informer le lecteur des métadonnées des annonces. Veuillez consulter les formats compatibles pour en savoir plus sur les formats de métadonnées minutées compatibles avec ExoPlayer. Les implémentations MediaSource
du SDK publicitaire personnalisé peuvent écouter les événements de métadonnées minutés du lecteur à l'aide de Player.Listener.onMetadata
.