Chèn quảng cáo

Bạn có thể sử dụng ExoPlayer để 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 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 đang 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 XML VAST hoặc VMAP. Dữ liệu này có thể bao gồm vị trí tín hiệu dừng quảng cáo tương ứng với điểm bắt đầu nội dung, URI nội dung nghe nhìn thực tế 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ề quảng cáo sẽ phát. Việc này có một số lợi ích:

  • Người chơi 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 cách sử dụng API của họ.
  • Các thành phần trên giao diện người dùng ExoPlayer có thể tự động hiển thị điểm đánh dấu cho vị trí quảng cáo và thay đổi hành vi của các thành phần đó tuỳ thuộc vào việc quảng cáo có đang phát hay không.
  • Trong nội bộ, người chơi có thể duy trì một vùng đệm nhất quán khi chuyển đổi giữa quảng cáo và nội dung.

Trong cách thiết lập này, người chơi đảm nhiệm việc chuyển đổi giữa quảng cáo và nội dung, nghĩa là ứng dụng không cần quan tâm đế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 tính năng chèn quảng cáo phía máy khách, bạn nên đặt quảng cáo ở 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 đối với các mục nội dung đa phương tiện chỉ định thẻ quảng cáo, bạn cần phải 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();

Trong 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 AdsLoader từ AdsLoader.Provider và sử dụng giá trị này để chèn quảng cáo do thẻ quảng cáo của mục nội dung đa phương tiện xác định.

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ả dưới đây.

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 đa phương tiệ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 đa phương tiện, URI nội dung và URI thẻ quảng cáo. Tức là người dùng sẽ thấy quảng cáo cho mọi mục nội dung đa phương tiện có quảng cáo có mã nội dung đa phương tiện hoặc URI nội dung riêng biệt, ngay cả khi URI thẻ quảng cáo khớp với nhau. Nếu một mục nội dung đa phương tiện được lặp lại, người dùng sẽ chỉ thấy các quảng cáo tương ứng một lần (trạng thái phát quảng cáo lưu trữ liệu quảng cáo đã được phát hay chưa, vì vậy, các quảng cáo này sẽ bị bỏ qua sau lần đầu tiên xuất hiện).

Bạn có thể tuỳ chỉnh hành vi này bằng cách truyền giá trị nhận dạng quảng cáo mờ với trạng thái phát quảng cáo cho một mục nội dung nghe nhìn nhất định được liên kết, dựa trên mức cân bằng đối tượng. Dưới đây là ví dụ, trong đó 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ì tổ hợp mã nhận dạng nội dung đa 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. Ảnh hưởng của việc này là quảng cáo sẽ chỉ tải một lần và người dùng sẽ không nhìn 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);

Thư viện IMA ExoPlayer

Thư viện IMA ExoPlayer 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ợ 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ý chế độ chạy ở chế độ 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à bao gồm một số thẻ quảng cáo VAST/VMAP mẫu trong danh sách mẫu.

Những điểm cần lưu ý về giao diện người dùng

Theo mặc định, PlayerView ẩn các chế độ đ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. SDK IMA sẽ hiển thị các chế độ xem bổ sung bên trên trình phát khi quảng cáo đang phát (ví dụ: đường liên kết "thông tin khác" và nút bỏ qua, nếu có).

SDK IMA có thể báo cáo liệu quảng cáo có bị che khuất bởi các chế độ xem do ứng dụng cung cấp được hiển thị ở đầu trình phát hay không. Các ứng dụng cần phủ các khung hiển thị cần thiết để điều khiển chế độ phát phải đăng ký chúng với SDK IMA để có thể loại bỏ những khung hiển thị này khỏi phép tính khả năng xem. Khi sử dụng PlayerView làm AdViewProvider, lớp này sẽ tự động đăng ký các lớp phủ điều khiển. Các ứng dụng sử dụng giao diện người dùng tuỳ chỉnh của trình phát 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 Đo lường mở trong SDK IMA.

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ể hiển thị trong "vùng" trên giao diện người dùng của ứng dụng. Các khe này có thể được chuyển qua ImaAdsLoader.Builder.setCompanionAdSlots(slots). Để biết thêm thông tin, hãy xem Thêm quảng cáo đồng hành.

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, không phải để 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 cho trường hợp sử dụng 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 tính năng tích hợp ExoPlayer hay chưa. Nếu không, bạn nên triển khai AdsLoader tuỳ chỉnh bao bọc SDK quảng cáo của bên thứ ba, vì phương pháp này mang lại các lợi ích của AdsMediaSource được mô tả ở trên. ImaAdsLoader đóng vai trò là một ví dụ 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 quảng cáo và đoạn 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(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);

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, hay 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ả phân khúc nội dung và phân khúc 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ề cách 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ủ, máy khách có thể 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, ứng dụng 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 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 nhiệm vụ này cho thao tác chèn quảng cáo phía máy chủ MediaSource cho các URI bằ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 IMA ExoPlayer

Thư viện IMA ExoPlayer 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 vào ứng dụng của bạn. Thư viện này bao bọc chức năng của SDK IMA DAI 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ụ: tính năng này cho phép bạn sử dụng các phương thức như Player.isPlayingAd(), theo dõi các chuyển đổi của quảng cáo nội dung và cho phép trình phát xử lý logic phát lại quảng cáo như bỏ qua các 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á tài sản IMA hoặc mã nguồn nội dung và mã 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 không còn sử dụng:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Những điểm cần lưu ý về giao diện người dùng

Những điều cần cân nhắc về giao diện người dùng như khi 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ể hiển thị trong "vùng" trên giao diện người dùng của ứng dụng. Các khe này có thể được chuyển qua ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots). Để biết thêm thông tin, hãy xem Thêm quảng cáo đồng hành.

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 tính năng 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 bằng 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 ủy quyền cho ServerSideAdInsertionMediaSource chung. Mục đích này bao bọc luồng MediaSource, đồng thời cho phép người dùng đặt và cập nhật AdPlaybackState biểu thị siêu dữ liệu quảng cáo.

Thông thường, các luồng quảng cáo được chèn phía máy chủ chứa các sự kiện được tính giờ để 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ó tính thời gian mà ExoPlayer hỗ trợ. Việc 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 tính giờ từ trình phát bằng cách sử dụng Player.Listener.onMetadata.