Penyisipan iklan

ExoPlayer dapat digunakan untuk penyisipan iklan sisi klien dan sisi server.

Penyisipan iklan sisi klien

Dalam penyisipan iklan sisi klien, pemutar beralih antara memuat media dari URL yang berbeda saat pemutar beralih antara memutar konten dan iklan. Informasi tentang iklan dimuat secara terpisah dari media, seperti dari tag iklan VAST atau VMAP XML. Hal ini dapat mencakup posisi tanda iklan relatif terhadap awal konten, URI dan metadata media iklan yang sebenarnya, seperti apakah iklan tertentu dapat dilewati atau tidak.

Saat menggunakan AdsMediaSource ExoPlayer untuk penyisipan iklan sisi klien, pemain memiliki informasi tentang iklan yang akan diputar. Hal ini memiliki beberapa manfaat:

  • Pemutar dapat menampakkan metadata dan fungsi terkait iklan menggunakan API-nya.
  • Komponen UI ExoPlayer dapat menampilkan penanda untuk posisi iklan secara otomatis, dan mengubah perilakunya bergantung pada apakah iklan diputar atau tidak.
  • Secara internal, pemutar dapat mempertahankan buffering yang konsisten di seluruh transisi antara iklan dan konten.

Dalam penyiapan ini, pemutar akan menangani peralihan antara iklan dan konten, yang berarti bahwa aplikasi tidak perlu menangani kontrol beberapa pemutar latar belakang/latar depan yang terpisah untuk iklan dan konten.

Saat menyiapkan video konten dan tag iklan untuk digunakan dengan penyisipan iklan sisi klien, iklan idealnya harus diposisikan pada contoh sinkronisasi (keyframe) dalam video konten sehingga pemutar dapat melanjutkan pemutaran konten dengan lancar.

Dukungan iklan deklaratif

URI tag iklan dapat ditentukan saat membuat 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();

Guna mengaktifkan dukungan pemutar untuk item media yang menentukan tag iklan, Anda harus membuat dan memasukkan DefaultMediaSourceFactory yang dikonfigurasi dengan AdsLoader.Provider dan AdViewProvider saat membuat pemutar:

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();

Secara internal, DefaultMediaSourceFactory akan menggabungkan sumber media konten di AdsMediaSource. AdsMediaSource akan mendapatkan AdsLoader dari AdsLoader.Provider dan menggunakannya untuk menyisipkan iklan seperti yang ditetapkan oleh tag iklan item media.

PlayerView ExoPlayer mengimplementasikan AdViewProvider. Library IMA ExoPlayer menyediakan AdsLoader yang mudah digunakan, seperti yang dijelaskan di bawah ini.

Playlist dengan iklan

Saat memutar playlist dengan beberapa item media, perilaku default-nya adalah meminta tag iklan dan menyimpan status pemutaran iklan satu kali untuk setiap kombinasi ID media, URI konten, dan URI tag iklan. Artinya, pengguna akan melihat iklan untuk setiap item media dengan iklan yang memiliki ID media atau URI konten yang berbeda, meskipun URI tag iklan cocok. Jika item media diulang, pengguna akan melihat iklan yang sesuai hanya sekali (status pemutaran iklan menyimpan apakah iklan telah diputar sehingga iklan akan dilewati setelah kejadian pertama).

Anda dapat menyesuaikan perilaku ini dengan meneruskan ID iklan buram yang akan ditautkan dengan status pemutaran iklan untuk item media tertentu, berdasarkan kesetaraan objek. Berikut adalah contoh jika status pemutaran iklan ditautkan hanya ke URI tag iklan, bukan kombinasi ID media dan URI tag iklan, dengan meneruskan URI tag iklan sebagai ID iklan. Akibatnya, iklan hanya akan dimuat sekali dan pengguna tidak akan melihat iklan di item kedua saat memutar playlist dari awal hingga akhir.

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);

Library IMA ExoPlayer

Library IMA ExoPlayer menyediakan ImaAdsLoader, yang memudahkan untuk mengintegrasikan penyisipan iklan sisi klien ke dalam aplikasi Anda. Library ini menggabungkan fungsi IMA SDK sisi klien untuk mendukung penyisipan iklan VAST/VMAP. Untuk mengetahui petunjuk penggunaan library, termasuk cara menangani pemutaran di latar belakang dan melanjutkan pemutaran, lihat README.

Aplikasi demo menggunakan library IMA, dan menyertakan beberapa contoh tag iklan VAST/VMAP dalam daftar contoh.

Pertimbangan UI

PlayerView menyembunyikan kontrol transportnya selama pemutaran iklan secara default, tetapi aplikasi dapat mengaktifkan/menonaktifkan perilaku ini dengan memanggil setControllerHideDuringAds. IMA SDK akan menampilkan penayangan tambahan di bagian atas pemutar saat iklan sedang diputar (misalnya, link "info selengkapnya" dan tombol lewati, jika ada).

IMA SDK dapat melaporkan apakah iklan terhalang oleh tampilan yang disediakan aplikasi yang dirender di bagian atas pemutar. Aplikasi yang perlu menempatkan tampilan yang penting untuk mengontrol pemutaran harus mendaftarkannya ke IMA SDK agar tampilan tersebut dapat dihilangkan dari penghitungan visibilitas. Saat menggunakan PlayerView sebagai AdViewProvider, overlay akan otomatis mendaftarkan overlay kontrolnya. Aplikasi yang menggunakan UI pemutar kustom harus mendaftarkan tampilan overlay dengan menampilkannya dari AdViewProvider.getAdOverlayInfos.

Untuk informasi selengkapnya tentang tampilan overlay, lihat Pengukuran Terbuka di IMA SDK.

Iklan pengiring

Beberapa tag iklan berisi iklan pengiring tambahan yang dapat ditampilkan di 'slot' di UI aplikasi. Slot ini dapat diteruskan melalui ImaAdsLoader.Builder.setCompanionAdSlots(slots). Untuk informasi lebih lanjut, lihat Menambahkan Iklan Pengiring.

Iklan mandiri

IMA SDK dirancang untuk menyisipkan iklan ke dalam konten media, bukan untuk memutar iklan yang berdiri sendiri. Oleh karena itu, pemutaran iklan mandiri tidak didukung oleh library IMA. Sebaiknya gunakan Google Mobile Ads SDK untuk kasus penggunaan ini.

Menggunakan SDK iklan pihak ketiga

Jika Anda perlu memuat iklan melalui SDK iklan pihak ketiga, sebaiknya periksa apakah SDK tersebut sudah menyediakan integrasi ExoPlayer. Jika belum, menerapkan AdsLoader kustom yang menggabungkan SDK iklan pihak ketiga adalah pendekatan yang direkomendasikan, karena memberikan manfaat seperti AdsMediaSource yang dijelaskan di atas. ImaAdsLoader berfungsi sebagai contoh implementasi.

Atau, Anda dapat menggunakan dukungan playlist ExoPlayer untuk membuat urutan iklan dan klip konten:

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);

Penyisipan iklan sisi server

Dalam penyisipan iklan sisi server (juga disebut penyisipan iklan dinamis, atau DAI), aliran media berisi iklan dan konten. Manifes DASH dapat menunjuk ke segmen konten dan iklan, mungkin dalam periode yang berbeda. Untuk HLS, lihat dokumentasi Apple tentang menggabungkan iklan ke dalam playlist.

Saat menggunakan penyisipan iklan sisi server, klien mungkin perlu me-resolve URL media secara dinamis untuk mendapatkan streaming yang digabungkan, klien mungkin perlu menampilkan overlay iklan di UI, atau mungkin perlu melaporkan peristiwa ke SDK iklan atau server iklan.

DefaultMediaSourceFactory ExoPlayer dapat mendelegasikan semua tugas ini ke penyisipan iklan sisi server MediaSource untuk URI menggunakan skema 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();

Library IMA ExoPlayer

Library IMA ExoPlayer menyediakan ImaServerSideAdInsertionMediaSource, yang memudahkan integrasi dengan streaming iklan yang disisipkan sisi server IMA di aplikasi Anda. Library ini menggabungkan fungsi IMA DAI SDK untuk Android dan sepenuhnya mengintegrasikan metadata iklan yang diberikan ke pemutar. Misalnya, hal ini memungkinkan Anda menggunakan metode seperti Player.isPlayingAd(), memproses transisi iklan konten dan memungkinkan pemutar menangani logika pemutaran iklan seperti melewati iklan yang sudah diputar.

Untuk menggunakan class ini, Anda perlu menyiapkan ImaServerSideAdInsertionMediaSource.AdsLoader dan ImaServerSideAdInsertionMediaSource.Factory lalu menghubungkannya ke pemutar:

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);

Muat kunci aset IMA, atau ID sumber konten dan ID video, dengan membuat URL dengan 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));

Terakhir, lepaskan pemuat iklan Anda setelah tidak digunakan lagi:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Pertimbangan UI

Pertimbangan UI yang sama seperti penyisipan iklan sisi klien juga berlaku untuk penyisipan iklan sisi server.

Iklan pengiring

Beberapa tag iklan berisi iklan pengiring tambahan yang dapat ditampilkan di 'slot' di UI aplikasi. Slot ini dapat diteruskan melalui ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots). Untuk informasi lebih lanjut, lihat Menambahkan Iklan Pengiring.

Menggunakan SDK iklan pihak ketiga

Jika Anda perlu memuat iklan menggunakan SDK iklan pihak ketiga, sebaiknya periksa apakah SDK tersebut sudah menyediakan integrasi ExoPlayer. Jika tidak, sebaiknya sediakan MediaSource kustom yang menerima URI dengan skema ssai:// yang mirip dengan ImaServerSideAdInsertionMediaSource.

Logika sebenarnya untuk membuat struktur iklan dapat didelegasikan ke ServerSideAdInsertionMediaSource tujuan umum, yang menggabungkan MediaSource aliran data dan memungkinkan pengguna menetapkan serta memperbarui AdPlaybackState yang mewakili metadata iklan.

Sering kali, streaming iklan yang disisipkan sisi server berisi peristiwa berjangka waktu untuk memberi tahu pemain tentang metadata iklan. Lihat format yang didukung untuk mengetahui informasi tentang format metadata dengan waktu yang didukung oleh ExoPlayer. Penerapan SDK iklan kustom MediaSource dapat memproses peristiwa metadata dengan waktu dari pemutar menggunakan Player.Listener.onMetadata.