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 chuyển đổi giữa chế độ tải nội dung nghe nhìn từ nhiều URL khi chuyển đổi giữa chế độ phát nội dung 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. Dữ liệu này có thể bao gồm vị trí của tín hiệu quảng cáo so với vị trí bắt đầu nội dung, URI nội dung nghe nhìn quảng cáo 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:

  • 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ị điểm đánh dấu cho vị trí quảng cáo và thay đổi hành vi của các điểm đánh dấu đó tuỳ thuộc vào việc quảng cáo có đang phát hay không.
  • Trong nội bộ, trình phát có thể duy trì vùng đệm nhất quán trong 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, nghĩa là ứng dụng không cần phải kiểm soát nhiều trình phát nền/tiền cảnh 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 bạn nên đặt quảng cáo 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 đa phương tiện chỉ định thẻ quảng cáo, bạn cần tạo và chèn 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 theo xác định của thẻ quảng cáo của mục nội dung đa phương tiện.

PlayerView của ExoPlayer triển khai AdViewProvider. Thư viện ExoPlayer IMA cung cấp 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 đ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ã nội dung đa phương tiệ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ã 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 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 mờ với 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ằng nhau 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ì tổ hợp mã nội dung nghe nhì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. Hiệu ứng này 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);

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. Thư viện này gói chức năng của SDK IMA phía máy khách để hỗ trợ tính năng 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ế độ nền và tiếp tục phát, vui lòng xem 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ều cần cân nhắc về giao diện người dùng

Theo mặc định, PlayerView sẽ ẩn các chế độ điều khiển truyền tải trong khi 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 khung hiển thị bổ sung ở đầu trình phát trong khi quảng cáo đang phát (ví dụ: đường liên kết "thông tin chi tiết" 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 khung hiển thị do ứng dụng cung cấp được hiển thị ở đầu trình phát hay không. Những ứng dụng cần phủ các thành phần hiển thị cần thiết để kiểm soát chế độ phát phải đăng ký các thành phần hiển thị đó với SDK IMA để có thể bỏ qua các thành phần hiển thị đó khỏi tính toán khả năng xem. Khi sử dụng PlayerView làm AdViewProvider, lớp này sẽ tự động đăng ký lớp phủ điều khiển. Các ứng dụng sử dụng giao diện người dùng trình phát tuỳ chỉnh phải đăng ký chế độ xem lớp phủ bằng cách trả về các chế độ xem đó từ AdViewProvider.getAdOverlayInfos.

Để biết thêm thông tin về chế độ xem lớp phủ, vui lòng xem phần Đ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 "khe" trên giao diện người dùng của ứng dụng. Các khe này có thể được truyền 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 đồ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, chứ không phải để tự phát quảng cáo độc lập. Do đó, thư viện IMA không hỗ trợ phát lại các 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 đó có tích hợp ExoPlayer hay không. 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ì cách này mang lại các lợi ích của AdsMediaSource như mô tả ở trên. ImaAdsLoader đóng vai trò là 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 trình tự 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 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 khúc quảng cáo, có thể ở các khoảng thời gian 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 một danh sách phát.

Khi sử dụng tính năng chèn quảng cáo phía máy chủ, ứng dụng có thể cần phải phân giải URL nội dung đa phương tiện một cách linh động để nhận luồng đã ghép nối, 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 tính năng chèn quảng cáo phía máy chủ MediaSource cho 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 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 gói chức năng của SDK IMA DAI dành cho Android và tích hợp đầy đủ 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(), nghe các 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 rồi kết nối các lớp này 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ã 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 trình tải này không còn được sử 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

Những điều cần cân nhắc về giao diện người dùng tương tự như khi chèn quảng cáo phía máy khách cũng áp dụng cho việc 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 "khe" trên 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 đồ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 đó có tích hợp sẵn ExoPlayer hay không. 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.

Bạn có thể uỷ quyền logic thực tế của việc tạo cấu trúc quảng cáo cho ServerSideAdInsertionMediaSource dùng cho mục đích chung. Lớp này sẽ bao bọc luồng MediaSource và cho phép người dùng đặt và 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 tính giờ để thông báo cho người chơi về siêu dữ liệu quảng cáo. Vui lòng xem phần định dạng được hỗ trợ để biết thông tin về các định dạng siêu dữ liệu theo thời gian mà ExoPlayer hỗ trợ. Các hoạt động triển khai MediaSource SDK quảng cáo tuỳ chỉnh có thể theo dõi các sự kiện siêu dữ liệu theo thời gian của trình phát bằng cách sử dụng Player.Listener.onMetadata.