ExoPlayera można używać do wstawiania reklam po stronie klienta i po stronie serwera.
Wstawianie reklam po stronie klienta
Przy wstawianiu reklam po stronie klienta odtwarzacz przełącza się między wczytywaniem multimediów z różnych adresów URL, gdy przechodzi między odtwarzanymi treściami a reklamami. Informacje o reklamach są wczytywane niezależnie od multimediów, np. z tagu reklamy VAST lub VMAP w formacie XML. Może to obejmować pozycje wstawienia reklamy względem początku treści, rzeczywiste identyfikatory URI multimediów reklam i metadane, np. to, czy daną reklamę można pominąć.
Gdy używasz obiektu AdsMediaSource
ExoPlayer do wstawiania reklam po stronie klienta, odtwarzacz otrzymuje informacje o reklamach, które mają zostać wyświetlone. Ma to kilka zalet:
- Odtwarzacz może udostępniać metadane i funkcje związane z reklamami za pomocą interfejsu API.
- Komponenty interfejsu ExoPlayer mogą automatycznie wyświetlać znaczniki pozycji reklam i zmieniać ich działanie w zależności od tego, czy reklama jest odtwarzana.
- Wewnętrznie odtwarzacz może utrzymywać spójny bufor podczas przejść między reklamami a treściami.
W takiej konfiguracji odtwarzacz przełącza się między reklamami a treścią, co oznacza, że aplikacje nie muszą sterować wieloma oddzielnymi odtwarzaczami w tle i na pierwszym planie w przypadku reklam i treści.
Przygotowując filmy i tagi reklam do obsługi wstawiania reklam po stronie klienta, najlepiej umieścić reklamy w próbkach synchronizacji (klatkach kluczowych) w filmie, aby odtwarzacz mógł płynnie wznowić odtwarzanie treści.
Deklaracja obsługi reklam
Podczas tworzenia elementu MediaItem
można określić identyfikator URI tagu reklamy:
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();
Aby umożliwić obsługę elementów multimedialnych, które określają tagi reklam, podczas tworzenia odtwarzacza musisz utworzyć i wstrzyknąć DefaultMediaSourceFactory
skonfigurowany z parametrami AdsLoader.Provider
i AdViewProvider
:
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();
Wewnętrznie DefaultMediaSourceFactory
umieszcza źródło multimediów
AdsMediaSource
. AdsMediaSource
pobierze z AdsLoader.Provider
klucz AdsLoader
i użyje go do wstawiania reklam zgodnie z definicją w tagu reklamy elementu multimedialnego.
Na urządzeniu ExoPlayer PlayerView
korzysta z metody AdViewProvider
. Biblioteka IMA ExoPlayer udostępnia łatwy w użyciu element AdsLoader
, jak opisano poniżej.
Playlisty z reklamami
Gdy odtwarzasz playlistę z wieloma elementami multimedialnymi, domyślnym działaniem jest pojedyncze żądanie tagu reklamy i zapisanie stanu odtwarzania reklamy dla każdej kombinacji identyfikatora multimediów, identyfikatora URI treści i identyfikatora URI tagu reklamy. Oznacza to, że użytkownicy zobaczą reklamy każdego elementu multimedialnego z reklamami, które mają inny identyfikator mediów lub identyfikator URI treści, nawet jeśli identyfikatory URI tagu reklamy są takie same. Jeśli element multimedialny się powtórzy, użytkownik zobaczy odpowiednie reklamy tylko raz (stan odtwarzania reklamy zapisuje, czy reklamy zostały odtworzone, więc są one pomijane po pierwszym wystąpieniu).
Możesz dostosować to działanie, przesyłając nieprzejrzysty identyfikator reklamy, z którą powiązany jest stan odtwarzania danego elementu multimedialnego (na podstawie równości obiektów). W tym przykładzie stan odtwarzania reklamy jest połączony tylko z identyfikatorem URI tagu reklamy, a nie z kombinacją identyfikatora mediów i identyfikatora URI tagu reklamy. W tym celu jako identyfikator reklamy należy przekazać identyfikator URI tagu reklamy. W efekcie reklamy wczytają się tylko raz i użytkownik nie widzi reklam w drugim elemencie podczas odtwarzania playlisty od początku do końca.
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);
Biblioteka IMA ExoPlayer
Biblioteka IMA ExoPlayer udostępnia pakiet ImaAdsLoader
, który ułatwia integrację wstawiania reklam po stronie klienta w aplikacji. Obejmuje funkcje pakietu IMA SDK po stronie klienta umożliwiającej wstawianie reklam VAST/VMAP. Instrukcje korzystania z biblioteki, w tym obsługi odtwarzania w tle i wznawiania odtwarzania, znajdziesz w README.
Aplikacja demonstracyjna korzysta z biblioteki IMA i na liście przykładowej znajduje się kilka przykładowych tagów reklam VAST/VMAP.
Uwagi na temat interfejsu użytkownika
PlayerView
domyślnie ukrywa elementy sterujące przesyłaniem podczas odtwarzania reklam, ale aplikacje mogą przełączać ten sposób działania, wywołując metodę setControllerHideDuringAds
. Podczas odtwarzania reklamy pakiet IMA SDK wyświetla dodatkowe widoki u góry odtwarzacza (np. link „więcej informacji” lub przycisk pominięcia, jeśli ma to zastosowanie).
Pakiet IMA SDK może informować, czy reklamy są zasłonięte przez widoki dostarczane przez aplikację renderowane na górze odtwarzacza. Aplikacje, które muszą nakładać widoki danych niezbędne do kontrolowania odtwarzania, muszą zarejestrować je w IMA SDK, aby mogły zostać pominięte w obliczeniach widoczności. Gdy używasz elementu PlayerView
jako AdViewProvider
, automatycznie rejestruje on nakładki kontrolne. Aplikacje, które używają niestandardowego interfejsu odtwarzacza, muszą rejestrować wyświetlenia nakładki, zwracając je z AdViewProvider.getAdOverlayInfos
.
Więcej informacji o widokach z nakładką znajdziesz w artykule o korzystaniu z Open Measurement w pakiecie IMA SDK.
Reklamy towarzyszące
Niektóre tagi reklam zawierają dodatkowe reklamy towarzyszące, które mogą się pojawiać w „boksach” w interfejsie aplikacji. Przedziały te można przekazywać przez ImaAdsLoader.Builder.setCompanionAdSlots(slots)
. Więcej informacji znajdziesz w artykule Dodawanie reklam towarzyszących.
Samodzielne reklamy
Pakiet IMA SDK jest przeznaczony do wstawiania reklam do treści multimedialnych, a nie do samodzielnego odtwarzania reklam. Z tego względu biblioteka IMA nie obsługuje odtwarzania samodzielnych reklam. W tym przypadku zalecamy użycie pakietu SDK do reklam mobilnych Google.
Korzystanie z pakietu SDK do wyświetlania reklam innej firmy
Jeśli chcesz wczytywać reklamy za pomocą pakietu SDK do wyświetlania reklam innej firmy, sprawdź, czy zapewnia on już integrację z ExoPlayer. W przeciwnym razie zalecamy implementację niestandardowego tagu AdsLoader
, który pakuje pakiet SDK do wyświetlania reklam innej firmy, ponieważ zapewnia on zalety AdsMediaSource
opisane powyżej.
ImaAdsLoader
działa jako przykładowa implementacja.
Możesz też skorzystać z obsługi playlist w ExoPlayer, by utworzyć sekwencję reklam i klipów treści:
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);
Wstawianie reklam po stronie serwera
W przypadku wstawiania reklam po stronie serwera (zwanego też dynamicznym wstawianiem reklam lub DAI) strumień multimediów zawiera zarówno reklamy, jak i treść. Plik manifestu DASH może wskazywać zarówno segmenty treści, jak i reklamy, zwykle w oddzielnych okresach. W przypadku HLS zapoznaj się z dokumentacją firmy Apple dotyczącą dodawania reklam do playlisty.
Gdy korzystasz z wstawienia reklamy po stronie serwera, klient musi dynamicznie uzyskiwać adres URL multimediów, aby uzyskać połączony strumień. Może też być konieczne wyświetlanie nakładek na reklamy w interfejsie lub zgłaszanie zdarzeń do pakietu SDK reklam lub serwera reklam.
Element DefaultMediaSourceFactory
ExoPlayer może przekazać wszystkie te zadania do wstawiania reklam po stronie serwera MediaSource
dla identyfikatorów URI, korzystając ze schematu 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();
Biblioteka IMA ExoPlayer
Biblioteka IMA DAI w pakiecie ImaServerSideAdInsertionMediaSource
ułatwia integrację ze strumieniami reklam wstawianymi po stronie serwera IMA. Ten pakiet obejmuje funkcje pakietu IMA DAI SDK na Androida i w pełni integruje dostarczone metadane reklam z odtwarzaczem. Pozwala to np. używać metod takich jak Player.isPlayingAd()
, odsłuchiwać przejścia między reklamami i treścią oraz umożliwiać odtwarzaczowi obsługę logiki odtwarzania reklamy, np. pomijanie już odtwarzanych reklam.
Aby korzystać z tej klasy, musisz skonfigurować ImaServerSideAdInsertionMediaSource.AdsLoader
i ImaServerSideAdInsertionMediaSource.Factory
oraz połączyć je z odtwarzaczem:
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);
Wczytaj klucz komponentu IMA lub identyfikator źródła treści i identyfikator filmu, tworząc URL za pomocą funkcji 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));
Na koniec zwolnij program wczytujący reklamy, gdy nie będzie już używany:
Kotlin
adsLoader.release()
Java
adsLoader.release();
Uwagi na temat interfejsu użytkownika
W przypadku wstawiania reklam po stronie serwera obowiązują te same zasady dotyczące interfejsu co w przypadku wstawiania reklam po stronie klienta.
Reklamy towarzyszące
Niektóre tagi reklam zawierają dodatkowe reklamy towarzyszące, które mogą się pojawiać w „boksach” w interfejsie aplikacji. Przedziały te można przekazywać przez ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots)
.
Więcej informacji znajdziesz w artykule Dodawanie reklam towarzyszących.
Korzystanie z pakietu SDK do wyświetlania reklam innej firmy
Jeśli chcesz wczytywać reklamy przy użyciu pakietu SDK do wyświetlania reklam innej firmy, sprawdź, czy zapewnia on już integrację z ExoPlayer. Jeśli nie, zalecamy udostępnienie niestandardowego elementu MediaSource
, który akceptuje identyfikatory URI o schemacie ssai://
podobnym do ImaServerSideAdInsertionMediaSource
.
Logikę tworzenia struktury reklamy można przekazać do ogólnego przeznaczenia ServerSideAdInsertionMediaSource
, które opakowuje strumień MediaSource
i umożliwia użytkownikowi ustawianie i aktualizowanie elementu AdPlaybackState
reprezentującego metadane reklam.
Strumienie reklam wstawiane po stronie serwera często zawierają zdarzenia czasowe, które powiadamiają odtwarzacz o metadanych reklam. Zapoznaj się z obsługiwanymi formatami, aby dowiedzieć się, jakie formaty metadanych czasowych są obsługiwane przez ExoPlayer. Implementacje pakietu SDK do reklam niestandardowych MediaSource
mogą nasłuchiwać zdarzeń metadanych ograniczonych czasowo z odtwarzacza za pomocą Player.Listener.onMetadata
.