Chèn quảng cáo

Bạn có thể sử dụng ExoPlayer cho cả tính năng chèn quảng cáo phía máy khách và phía máy chủ.

Chèn quảng cáo phía máy khách

Trong tính năng chèn quảng cáo phía máy khách, trình phát sẽ chuyển đổi giữa việc tải nội dung nghe nhìn từ các URL khác nhau khi chuyển đổi giữa nội dung phát và quảng cáo. Thông tin về quảng cáo được tải riêng biệt với nội dung nghe nhìn, chẳng hạn như từ thẻ quảng cáo VAST hoặc VMAP XML. Thông tin này có thể bao gồm vị trí của dấu hiệu quảng cáo so với phần đầu nội dung, URI thực tế của nội dung nghe nhìn quảng cáo và siêu dữ liệu, chẳng hạn như liệu một quảng cáo nhất định có thể bỏ qua hay không.

Khi sử dụng AdsMediaSource của ExoPlayer để chèn quảng cáo phía máy khách, trình phát sẽ có thông tin về những quảng cáo sẽ phát. Việc này có một số lợi ích:

  • Trình phát có thể hiển thị siêu dữ liệu và chức năng liên quan đến quảng cáo bằng API của trình phát.
  • Các thành phần giao diện người dùng ExoPlayer có thể tự động hiển thị các điểm đánh dấu cho vị trí quảng cáo và thay đổi hành vi của chúng tuỳ thuộc vào việc quảng cáo có đang phát hay không.
  • Về nội bộ, trình phát có thể duy trì bộ nhớ đệm nhất quán trong các quá trình chuyển đổi giữa quảng cáo và nội dung.

Trong chế độ thiết lập này, trình phát sẽ đảm nhận việc chuyển đổi giữa quảng cáo và nội dung. Điều này có nghĩa là các ứng dụng không cần đảm nhận việc kiểm soát nhiều trình phát nền/nền trước riêng biệt cho quảng cáo và nội dung.

Khi chuẩn bị video nội dung và thẻ quảng cáo để sử dụng với tính năng chèn quảng cáo phía máy khách, tốt nhất là quảng cáo nên được đặt tại các mẫu đồng bộ hoá (khung hình chính) trong video nội dung để trình phát có thể tiếp tục phát nội dung một cách liền mạch.

Hỗ trợ quảng cáo khai báo

Bạn có thể chỉ định URI thẻ quảng cáo khi tạo 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();

Để bật tính năng hỗ trợ trình phát cho các mục nội dung nghe nhìn chỉ định thẻ quảng cáo, bạn cần tạo và chèn một DefaultMediaSourceFactory được định cấu hình bằng AdsLoader.ProviderAdViewProvider khi tạo trình phát:

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

Về nội bộ, DefaultMediaSourceFactory sẽ gói nguồn nội dung đa phương tiện trong một AdsMediaSource. AdsMediaSource sẽ lấy một AdsLoader từ AdsLoader.Provider và dùng mã này để chèn quảng cáo theo định nghĩa của thẻ quảng cáo của mục nội dung nghe nhìn.

PlayerView của ExoPlayer triển khai AdViewProvider. Thư viện ExoPlayer IMA cung cấp một AdsLoader dễ sử dụng, như mô tả bên dưới.

Danh sách phát có quảng cáo

Khi phát một danh sách phát có nhiều mục nội dung nghe nhìn, hành vi mặc định là yêu cầu thẻ quảng cáo và lưu trữ trạng thái phát quảng cáo một lần cho mỗi tổ hợp mã nhận dạng nội dung nghe nhìn, URI nội dung và URI thẻ quảng cáo. Điều này có nghĩa là người dùng sẽ thấy quảng cáo cho mọi mục nội dung nghe nhìn có quảng cáo có mã nhận dạng nội dung nghe nhìn hoặc URI nội dung riêng biệt, ngay cả khi URI thẻ quảng cáo trùng khớp. Nếu một mục nội dung nghe nhìn được phát lại, người dùng sẽ chỉ thấy quảng cáo tương ứng một lần (trạng thái phát quảng cáo lưu trữ thông tin về việc quảng cáo đã được phát hay chưa, vì vậy, quảng cáo sẽ bị bỏ qua sau lần xuất hiện đầu tiên).

Bạn có thể tuỳ chỉnh hành vi này bằng cách truyền một giá trị nhận dạng quảng cáo không công khai mà trạng thái phát quảng cáo cho một mục nội dung đa phương tiện nhất định được liên kết, dựa trên sự bình đẳng của đối tượng. Sau đây là ví dụ về trường hợp trạng thái phát quảng cáo chỉ được liên kết với URI thẻ quảng cáo, thay vì kết hợp mã nhận dạng phương tiện và URI thẻ quảng cáo, bằng cách truyền URI thẻ quảng cáo làm giá trị nhận dạng quảng cáo. Kết quả là quảng cáo sẽ chỉ tải một lần và người dùng sẽ không thấy quảng cáo trên mục thứ hai khi phát danh sách phát từ đầu đến cuối.

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

Tính năng chèn quảng cáo phía máy khách có hướng dẫn của máy chủ

ExoPlayer đi kèm với HlsInterstitialsAdsLoader hỗ trợ việc tự động chèn quảng cáo được xác định trong danh sách phát HLS ở phía máy khách. Xem phần về HlsInterstitialsAdsLoader trên trang HLS.

Thư viện ExoPlayer IMA

Thư viện ExoPlayer IMA cung cấp ImaAdsLoader, giúp bạn dễ dàng tích hợp tính năng chèn quảng cáo phía máy khách vào ứng dụng của mình. Thư viện này gói chức năng của SDK IMA phía máy khách để hỗ trợ việc chèn quảng cáo VAST/VMAP. Để biết hướng dẫn về cách sử dụng thư viện, bao gồm cả cách xử lý việc chuyển xuống nền và tiếp tục phát, vui lòng xem phần README.

Ứng dụng minh hoạ sử dụng thư viện IMA và có một số thẻ quảng cáo VAST/VMAP mẫu trong danh sách mẫu.

Những điều cần cân nhắc về giao diện người dùng

Theo mặc định, PlayerView sẽ ẩn các nút điều khiển truyền tải trong quá trình phát quảng cáo, nhưng các ứng dụng có thể bật/tắt hành vi này bằng cách gọi setControllerHideDuringAds. IMA SDK sẽ hiển thị các khung hiển thị bổ sung ở trên cùng của trình phát trong khi quảng cáo đang phát (ví dụ: đường liên kết "thêm thông tin" và nút bỏ qua, nếu có).

SDK IMA có thể báo cáo liệu quảng cáo có bị các khung hiển thị do ứng dụng cung cấp che khuất hay không, được hiển thị ở trên cùng của trình phát. Những ứng dụng cần phủ các khung hiển thị cần thiết để kiểm soát hoạt động phát phải đăng ký các khung hiển thị đó bằng SDK IMA để có thể bỏ qua các khung hiển thị đó trong quá trình tính toán khả năng xem. Khi sử dụng PlayerView làm AdViewProvider, thành phần này sẽ tự động đăng ký các lớp phủ điều khiển. Ứng dụng sử dụng giao diện người dùng trình phát tuỳ chỉnh phải đăng ký các khung hiển thị lớp phủ bằng cách trả về các khung hiển thị đó từ AdViewProvider.getAdOverlayInfos.

Để biết thêm thông tin về chế độ xem lớp phủ, hãy xem bài viết Open Measurement trong IMA SDK.

Quảng cáo đồng hành

Một số thẻ quảng cáo chứa quảng cáo đồng hành bổ sung có thể xuất hiện trong "các vị trí" trong giao diện người dùng của ứng dụng. Bạn có thể truyền các khe này thông qua ImaAdsLoader.Builder.setCompanionAdSlots(slots). Để biết thêm thông tin, hãy xem bài viết Thêm quảng cáo đi kèm.

Quảng cáo độc lập

SDK IMA được thiết kế để chèn quảng cáo vào nội dung nghe nhìn, chứ không phải để tự phát quảng cáo độc lập. Do đó, thư viện IMA không hỗ trợ việc phát quảng cáo độc lập. Bạn nên sử dụng SDK Quảng cáo của Google trên thiết bị di động thay vì SDK này.

Sử dụng SDK quảng cáo của bên thứ ba

Nếu cần tải quảng cáo thông qua SDK quảng cáo của bên thứ ba, bạn nên kiểm tra xem SDK đó đã cung cấp một chế độ tích hợp ExoPlayer hay chưa. Nếu không, bạn nên triển khai một AdsLoader tuỳ chỉnh bao bọc SDK quảng cáo của bên thứ ba, vì AdsMediaSource này mang lại những lợi ích được mô tả ở trên. ImaAdsLoader đóng vai trò là một ví dụ về cách triển khai.

Ngoài ra, bạn có thể sử dụng tính năng hỗ trợ danh sách phát của ExoPlayer để tạo một chuỗi gồm các quảng cáo và đoạn trích nội dung:

Kotlin

// A pre-roll ad.
val preRollAd = MediaItem.fromUri(preRollAdUri)
// The start of the content.
val contentStart =
  MediaItem.Builder()
    .setUri(contentUri)
    .setClippingConfiguration(MediaItem.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(MediaItem.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 MediaItem.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 MediaItem.ClippingConfiguration.Builder().setStartPositionMs(120_000).build())
        .build();

// Build the playlist.
player.addMediaItem(preRollAd);
player.addMediaItem(contentStart);
player.addMediaItem(midRollAd);
player.addMediaItem(contentEnd);

Chèn quảng cáo phía máy chủ

Trong tính năng chèn quảng cáo phía máy chủ (còn gọi là chèn quảng cáo động hoặc DAI), luồng nội dung nghe nhìn chứa cả quảng cáo và nội dung. Tệp kê khai DASH có thể trỏ đến cả nội dung và phân đoạn quảng cáo, có thể ở các giai đoạn riêng biệt. Đối với HLS, hãy xem tài liệu của Apple về việc kết hợp quảng cáo vào danh sách phát.

Khi sử dụng tính năng chèn quảng cáo phía máy chủ, có thể máy khách cần phân giải URL nội dung nghe nhìn một cách linh động để nhận được luồng được ghép, có thể cần hiển thị lớp phủ quảng cáo trong giao diện người dùng hoặc có thể cần báo cáo các sự kiện cho SDK quảng cáo hoặc máy chủ quảng cáo.

DefaultMediaSourceFactory của ExoPlayer có thể uỷ quyền tất cả các tác vụ này cho tính năng chèn quảng cáo phía máy chủ MediaSource cho các URI bằng cách sử dụng lược đồ 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();

Thư viện ExoPlayer IMA

Thư viện ExoPlayer IMA cung cấp ImaServerSideAdInsertionMediaSource, giúp bạn dễ dàng tích hợp với các luồng quảng cáo được chèn phía máy chủ của IMA trong ứng dụng. Thư viện này bao bọc chức năng của SDK DAI IMA cho Android và tích hợp hoàn toàn siêu dữ liệu quảng cáo được cung cấp vào trình phát. Ví dụ: điều này cho phép bạn sử dụng các phương thức như Player.isPlayingAd(), theo dõi các quá trình chuyển đổi nội dung-quảng cáo và cho phép trình phát xử lý logic phát quảng cáo như bỏ qua quảng cáo đã phát.

Để sử dụng lớp này, bạn cần thiết lập ImaServerSideAdInsertionMediaSource.AdsLoaderImaServerSideAdInsertionMediaSource.Factory, đồng thời kết nối chúng với trình phát:

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

Tải khoá thành phần IMA hoặc mã nhận dạng nguồn nội dung và mã nhận dạng video bằng cách tạo một URL bằng 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));

Cuối cùng, hãy phát hành trình tải quảng cáo khi bạn không dùng nữa:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Những điều cần cân nhắc về giao diện người dùng

Các điểm cần cân nhắc về giao diện người dùng tương tự như đối với tính năng chèn quảng cáo phía máy khách cũng áp dụng cho tính năng chèn quảng cáo phía máy chủ.

Quảng cáo đồng hành

Một số thẻ quảng cáo chứa quảng cáo đồng hành bổ sung có thể xuất hiện trong "các vị trí" trong giao diện người dùng của ứng dụng. Bạn có thể truyền các khe này thông qua ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots). Để biết thêm thông tin, hãy xem bài viết Thêm quảng cáo đi kèm.

Sử dụng SDK quảng cáo của bên thứ ba

Nếu cần tải quảng cáo bằng SDK quảng cáo của bên thứ ba, bạn nên kiểm tra xem SDK đó đã cung cấp một chế độ tích hợp ExoPlayer hay chưa. Nếu không, bạn nên cung cấp một MediaSource tuỳ chỉnh chấp nhận các URI có lược đồ ssai:// tương tự như ImaServerSideAdInsertionMediaSource.

Logic thực tế để tạo cấu trúc quảng cáo có thể được uỷ quyền cho ServerSideAdInsertionMediaSource cho mục đích chung, bao bọc một luồng MediaSource và cho phép người dùng đặt cũng như cập nhật AdPlaybackState đại diện cho siêu dữ liệu quảng cáo.

Thông thường, luồng quảng cáo được chèn phía máy chủ chứa các sự kiện có dấu thời gian để thông báo cho trình phát về siêu dữ liệu quảng cáo. Vui lòng xem các định dạng được hỗ trợ để biết thông tin về những định dạng siêu dữ liệu có dấu thời gian được ExoPlayer hỗ trợ. Các chế độ triển khai SDK quảng cáo tuỳ chỉnh MediaSource có thể theo dõi các sự kiện siêu dữ liệu có dấu thời gian từ trình phát bằng cách sử dụng Player.Listener.onMetadata.