Wstawianie reklam

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.