ExoPlayer kann sowohl für die clientseitige als auch für die serverseitige Anzeigenbereitstellung verwendet werden.
Clientseitige Anzeigenbereitstellung
Bei der clientseitigen Anzeigenbereitstellung wechselt der Player beim Übergang zwischen der Wiedergabe von Inhalten und Anzeigen zwischen dem Laden von Medien aus verschiedenen URLs. Informationen zu Anzeigen werden getrennt von den Medien geladen, z. B. aus einem XML-Anzeigen-Tag vom Typ VAST oder VMAP. Dazu gehören die Positionen der Anzeigen-Cues relativ zum Beginn des Inhalts, die tatsächlichen URIs der Anzeigenmedien und Metadaten wie die Überspringbarkeit einer bestimmten Anzeige.
Wenn du die AdsMediaSource
von ExoPlayer für die clientseitige Anzeigenbereitstellung verwendest, hat der Player Informationen zu den wiederzugebenden Anzeigen. Das hat mehrere Vorteile:
- Der Player kann über seine API Metadaten und Funktionen in Bezug auf Anzeigen freigeben.
- ExoPlayer-UI-Komponenten können Markierungen für Anzeigenpositionen automatisch anzeigen und ihr Verhalten ändern, je nachdem, ob eine Anzeige wiedergegeben wird.
- Intern kann der Player bei Übergängen zwischen Anzeigen und Inhalten einen konsistenten Puffer beibehalten.
Bei dieser Konfiguration kümmert sich der Player um den Wechsel zwischen Anzeigen und Inhalten. Das bedeutet, dass Apps nicht mehrere separate Player für den Hintergrund/Vordergrund für Anzeigen und Inhalte steuern müssen.
Wenn Sie Contentvideos und Anzeigen-Tags für die clientseitige Anzeigenbereitstellung vorbereiten, sollten Anzeigen idealerweise an Synchronisierungsbeispielen (Keyframes) im Contentvideo platziert werden, damit der Player die Wiedergabe des Contents nahtlos fortsetzen kann.
Unterstützung für deklarative Anzeigen
Ein Anzeigen-Tag-URI kann beim Erstellen eines MediaItem
angegeben werden:
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();
Wenn du die Player-Unterstützung für Medienelemente mit Anzeigen-Tags aktivieren möchtest, musst du beim Erstellen des Players ein DefaultMediaSourceFactory
mit einem AdsLoader.Provider
und einem AdViewProvider
erstellen und einfügen:
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();
Intern umschließt DefaultMediaSourceFactory
die Contentmedienquelle in einer AdsMediaSource
. Die AdsMediaSource
ruft eine AdsLoader
von der AdsLoader.Provider
ab und verwendet sie, um Anzeigen einzufügen, wie im Anzeigen-Tag des Medienelements definiert.
PlayerView
von ExoPlayer implementiert AdViewProvider
. Die ExoPlayer IMA-Bibliothek bietet eine einfach zu bedienende AdsLoader
, wie unten beschrieben.
Playlists mit Werbung
Wenn eine Playlist mit mehreren Medienelementen wiedergegeben wird, wird standardmäßig das Anzeigen-Tag angefordert und der Wiedergabestatus der Anzeige einmal für jede Kombination aus Medien-ID, Inhalts-URI und Anzeigen-Tag-URI gespeichert. Das bedeutet, dass Nutzern Anzeigen für jedes Medienelement mit Anzeigen mit einer eindeutigen Medien-ID oder einem eindeutigen Inhalts-URI präsentiert werden, auch wenn die URIs der Anzeigen-Tags übereinstimmen. Wenn ein Medienelement wiederholt wird, sieht der Nutzer die entsprechenden Anzeigen nur einmal. Im Wiedergabestatus der Anzeigen wird gespeichert, ob Anzeigen bereits wiedergegeben wurden, sodass sie nach dem ersten Vorkommen übersprungen werden.
Sie können dieses Verhalten anpassen, indem Sie eine intransparente Anzeigen-ID übergeben, mit der der Anzeigenwiedergabestatus für ein bestimmtes Medienelement basierend auf der Objektgleichheit verknüpft wird. In diesem Beispiel ist der Wiedergabestatus der Anzeige nur mit dem Anzeigen-Tag-URI verknüpft, nicht mit der Kombination aus Medien-ID und Anzeigen-Tag-URI. Dazu wird der Anzeigen-Tag-URI als Anzeigen-ID übergeben. Das hat zur Folge, dass Anzeigen nur einmal geladen werden und der Nutzer keine Anzeigen beim zweiten Element sieht, wenn er die Playlist von Anfang bis Ende abspielt.
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);
ExoPlayer IMA-Bibliothek
Die ExoPlayer IMA-Bibliothek bietet ImaAdsLoader
, sodass du die clientseitige Anzeigenbereitstellung ganz einfach in deine App einbinden kannst. Sie umhüllt die Funktionen des clientseitigen IMA SDK, um die Einbindung von VAST-/VMAP-Anzeigen zu unterstützen. Eine Anleitung zur Verwendung der Bibliothek, einschließlich der Wiedergabe im Hintergrund und der Wiederaufnahme der Wiedergabe, findest du in der README-Datei.
In der Demoanwendung wird die IMA-Bibliothek verwendet und die Beispielliste enthält mehrere Beispiel-VAST-/VMAP-Anzeigen-Tags.
Hinweise zur Benutzeroberfläche
PlayerView
blendet die Transportsteuerung während der Wiedergabe von Anzeigen standardmäßig aus. Apps können dieses Verhalten durch Aufrufen von setControllerHideDuringAds
umschalten. Das IMA SDK zeigt während der Wiedergabe einer Anzeige zusätzliche Ansichten über dem Player an, z. B. einen Link „Weitere Informationen“ und eine Schaltfläche zum Überspringen.
Das IMA SDK kann melden, ob Anzeigen von von der Anwendung bereitgestellten Ansichten verdeckt werden, die über dem Player gerendert werden. In Apps, in denen Ansichten eingeblendet werden müssen, die für die Wiedergabesteuerung unerlässlich sind, müssen diese Ansichten im IMA SDK registriert werden, damit sie bei der Sichtbarkeitsberechnung nicht berücksichtigt werden. Wenn Sie PlayerView
als AdViewProvider
verwenden, werden die Steuerelement-Overlays automatisch registriert. Apps, die eine benutzerdefinierte Player-UI verwenden, müssen Overlay-Ansichten registrieren, indem sie von AdViewProvider.getAdOverlayInfos
zurückgegeben werden.
Weitere Informationen zu Overlay-Aufrufen finden Sie unter Open Measurement im IMA SDK.
Companion-Anzeigen
Einige Anzeigen-Tags enthalten zusätzliche Companion-Anzeigen, die in „Slots“ in der App-Benutzeroberfläche ausgeliefert werden können. Diese Slots können über ImaAdsLoader.Builder.setCompanionAdSlots(slots)
übergeben werden. Weitere Informationen finden Sie unter Komplementaranzeigen hinzufügen.
Eigenständige Anzeigen
Das IMA SDK ist zum Einfügen von Anzeigen in Mediacontent gedacht, nicht zum eigenständigen Abspielen von Anzeigen. Daher wird die Wiedergabe von eigenständigen Anzeigen von der IMA-Bibliothek nicht unterstützt. Für diesen Anwendungsfall empfehlen wir stattdessen das Google Mobile Ads SDK.
Mit dem Anzeigen-SDK eines Drittanbieters
Wenn Sie Anzeigen über ein Anzeigen-SDK eines Drittanbieters laden müssen, sollten Sie prüfen, ob es bereits eine ExoPlayer-Integration bietet. Andernfalls wird empfohlen, eine benutzerdefinierte AdsLoader
zu implementieren, die das SDK für Drittanbieteranzeigen umschließt. Sie bietet die oben beschriebenen Vorteile von AdsMediaSource
.
ImaAdsLoader
dient als Beispielimplementierung.
Alternativ können Sie die Playlist-Unterstützung von ExoPlayer verwenden, um eine Sequenz von Anzeigen und Content-Clips zu erstellen:
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);
Serverseitige Anzeigenbereitstellung
Bei der serverseitigen Anzeigenbereitstellung (auch als dynamische Anzeigenbereitstellung bezeichnet) enthält der Medienstream sowohl Anzeigen als auch Content. Ein DASH-Manifest kann sowohl auf Inhalts- als auch auf Anzeigensegmente verweisen, möglicherweise in separaten Zeiträumen. Informationen zu HLS finden Sie in der Apple-Dokumentation zum Einbinden von Anzeigen in eine Playlist.
Bei der serverseitigen Anzeigenbereitstellung muss der Client möglicherweise die Medien-URL dynamisch auflösen, um den zusammengefügten Stream abzurufen. Außerdem muss er möglicherweise Anzeigen-Overlays in der Benutzeroberfläche anzeigen oder Ereignisse an ein Anzeigen-SDK oder einen Anzeigenserver melden.
Die DefaultMediaSourceFactory
von ExoPlayer kann alle diese Aufgaben an eine serverseitige Anzeigenbereitstellung MediaSource
für URIs mit dem ssai://
-Schema delegieren:
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();
ExoPlayer-IMA-Bibliothek
Die ExoPlayer IMA-Bibliothek bietet ImaServerSideAdInsertionMediaSource
, sodass sich die serverseitig eingefügten Anzeigenstreams von IMA in deine App einbinden lassen. Sie umschließt die Funktionen des IMA DAI SDK für Android und integriert die bereitgestellten Anzeigenmetadaten vollständig in den Player. So können Sie beispielsweise Methoden wie Player.isPlayingAd()
verwenden, Übergänge zwischen Inhalt und Anzeige beobachten und dem Player die Logik der Anzeigenwiedergabe wie das Überspringen bereits abgespielter Anzeigen überlassen.
Wenn du diese Klasse verwenden möchtest, musst du die ImaServerSideAdInsertionMediaSource.AdsLoader
und die ImaServerSideAdInsertionMediaSource.Factory
einrichten und mit dem Player verbinden:
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);
Lade deinen IMA-Asset-Schlüssel oder die Content-Quell-ID und die Video-ID, indem du eine URL mit ImaServerSideAdInsertionUriBuilder
erstellst:
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));
Entfernen Sie den Anzeigen-Lademechanismus, sobald er nicht mehr verwendet wird:
Kotlin
adsLoader.release()
Java
adsLoader.release();
Hinweise zur Benutzeroberfläche
Für die serverseitige Anzeigenbereitstellung gelten dieselben Überlegungen zur Benutzeroberfläche wie bei der clientseitigen Anzeigenbereitstellung.
Companion-Anzeigen
Einige Anzeigen-Tags enthalten zusätzliche Companion-Anzeigen, die in Anzeigenflächen auf einer App-Benutzeroberfläche erscheinen können. Diese Slots können über ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots)
übergeben werden.
Weitere Informationen finden Sie unter Komplementaranzeigen hinzufügen.
Mit dem Anzeigen-SDK eines Drittanbieters
Wenn du Anzeigen über ein Anzeigen-SDK eines Drittanbieters laden musst, solltest du prüfen, ob es bereits eine ExoPlayer-Integration bietet. Andernfalls empfehlen wir, eine benutzerdefinierte MediaSource
anzugeben, die URIs mit dem ssai://
-Schema akzeptiert, ähnlich wie ImaServerSideAdInsertionMediaSource
.
Die eigentliche Logik zum Erstellen der Anzeigenstruktur kann an den allgemeinen Zweck ServerSideAdInsertionMediaSource
delegiert werden, der einen Stream MediaSource
umschließt und es dem Nutzer ermöglicht, die AdPlaybackState
festzulegen und zu aktualisieren, die die Anzeigenmetadaten darstellen.
Serverseitig eingefügte Anzeigenstreams enthalten häufig zeitgesteuerte Ereignisse, um den Player über Anzeigenmetadaten zu informieren. Informationen zu den von ExoPlayer unterstützten Zeitmetadatenformaten findest du unter Unterstützte Formate. Bei MediaSource
-Implementierungen des Custom Ads SDK kann mit Player.Listener.onMetadata
auf zeitgesteuerte Metadatenereignisse vom Player gewartet werden.