Вставка рекламы

ExoPlayer можно использовать как для вставки рекламы на стороне клиента, так и на стороне сервера.

Вставка рекламы на стороне клиента

При вставке рекламы на стороне клиента плеер переключается между загрузкой медиафайлов с разных URL-адресов по мере перехода от воспроизводимого контента к рекламе. Информация о рекламе загружается отдельно от медиафайлов, например, из тега XML VAST или VMAP . Это может включать в себя позиции рекламных фрагментов относительно начала контента, фактические URI рекламных медиафайлов и метаданные, такие как возможность пропуска данной рекламы.

При использовании AdsMediaSource из ExoPlayer для вставки рекламы на стороне клиента, плеер получает информацию о воспроизводимой рекламе. Это дает ряд преимуществ:

  • Игрок может предоставлять доступ к метаданным и функционалу, связанным с рекламой, используя свой API.
  • Компоненты пользовательского интерфейса ExoPlayer могут автоматически отображать маркеры позиций рекламы и изменять свое поведение в зависимости от того, воспроизводится ли реклама.
  • Внутри системы плеер может поддерживать постоянный буфер при переходах между рекламой и контентом.

В этой конфигурации плеер сам переключается между рекламой и контентом, а это значит, что приложениям не нужно управлять несколькими отдельными плеерами для показа рекламы и контента в фоновом/активном режиме.

При подготовке видеороликов и рекламных тегов для использования с вставкой рекламы на стороне клиента, рекламу в идеале следует размещать в момент синхронизации (ключевые кадры) видеоролика, чтобы проигрыватель мог беспрепятственно возобновить воспроизведение контента.

Декларативная поддержка рекламы

URI рекламного тега можно указать при создании MediaItem :

Котлин

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

Для включения поддержки воспроизведения медиафайлов, содержащих рекламные теги, необходимо создать и внедрить DefaultMediaSourceFactory , настроенный с использованием AdsLoader.Provider и AdViewProvider при создании плеера:

Котлин

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

Внутри DefaultMediaSourceFactory оборачивает источник медиаконтента в AdsMediaSource . AdsMediaSource получает AdsLoader от AdsLoader.Provider и использует его для вставки рекламы в соответствии с рекламным тегом медиафайла.

PlayerView ExoPlayer реализует AdViewProvider . Библиотека IMA ExoPlayer предоставляет простой в использовании AdsLoader , как описано ниже.

Плейлисты с рекламой

При воспроизведении плейлиста, содержащего несколько медиафайлов, по умолчанию запрашивается рекламный тег и сохраняется состояние воспроизведения рекламы один раз для каждой комбинации идентификатора медиафайла, URI контента и URI рекламного тега. Это означает, что пользователи будут видеть рекламу для каждого медиафайла, содержащего рекламу с уникальным идентификатором медиафайла или URI контента, даже если URI рекламных тегов совпадают. Если медиафайл повторяется, пользователь увидит соответствующую рекламу только один раз (состояние воспроизведения рекламы хранит информацию о том, была ли реклама воспроизведена, поэтому она пропускается после первого показа).

Это поведение можно настроить, передав непрозрачный идентификатор рекламы, с которым связано состояние воспроизведения рекламы для данного медиафайла на основе равенства объектов. Вот пример, где состояние воспроизведения рекламы связано только с URI тега рекламы, а не с комбинацией идентификатора медиафайла и URI тега рекламы, путем передачи URI тега рекламы в качестве идентификатора рекламы. В результате реклама будет загружаться только один раз, и пользователь не увидит рекламу во втором элементе при воспроизведении плейлиста от начала до конца.

Котлин

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

Вставка рекламы на стороне клиента с управлением со стороны сервера

ExoPlayer поставляется с HlsInterstitialsAdsLoader , который поддерживает автоматическую вставку рекламы, определенной в плейлисте HLS, на стороне клиента. См. раздел о HlsInterstitialsAdsLoader на странице HLS .

Библиотека ExoPlayer IMA

Библиотека ExoPlayer IMA предоставляет ImaAdsLoader , что упрощает интеграцию вставки рекламы на стороне клиента в ваше приложение. Она использует функциональность клиентского SDK IMA для поддержки вставки рекламы VAST/VMAP. Инструкции по использованию библиотеки, включая обработку фонового режима и возобновление воспроизведения, см. в файле README .

Демонстрационное приложение использует библиотеку IMA и включает в себя несколько примеров рекламных тегов VAST/VMAP в списке примеров.

соображения пользовательского интерфейса

По умолчанию PlayerView скрывает элементы управления воспроизведением во время показа рекламы, но приложения могут изменить это поведение, вызвав метод setControllerHideDuringAds . В этом случае SDK IMA будет отображать дополнительные элементы поверх плеера во время воспроизведения рекламы (например, ссылку «подробнее» и кнопку «пропустить», если применимо).

IMA SDK может сообщать, перекрываются ли рекламные объявления представлениями, предоставляемыми приложением и отображаемыми поверх плеера. Приложениям, которым необходимо перекрывать представления, необходимые для управления воспроизведением, следует зарегистрировать их в IMA SDK, чтобы они не учитывались при расчете видимости. При использовании PlayerView в качестве AdViewProvider , он автоматически зарегистрирует свои элементы управления. Приложениям, использующим пользовательский интерфейс плеера, необходимо регистрировать элементы управления, возвращая их из AdViewProvider.getAdOverlayInfos .

Для получения дополнительной информации о наложенных представлениях см. раздел «Открытие измерений» в SDK IMA .

Сопутствующие объявления

Некоторые рекламные теги содержат дополнительные сопутствующие объявления, которые могут отображаться в «слотах» в пользовательском интерфейсе приложения. Эти слоты можно передать с помощью метода ImaAdsLoader.Builder.setCompanionAdSlots(slots) . Для получения дополнительной информации см. раздел «Добавление сопутствующих объявлений» .

Отдельные рекламные объявления

IMA SDK предназначен для вставки рекламы в медиаконтент, а не для воспроизведения отдельных рекламных объявлений. Поэтому воспроизведение отдельных рекламных объявлений не поддерживается библиотекой IMA. Для этой цели мы рекомендуем использовать Google Mobile Ads SDK .

Использование стороннего SDK для рекламы

Если вам необходимо загружать рекламу через сторонний SDK для рекламы, стоит проверить, предоставляет ли он уже интеграцию с ExoPlayer. Если нет, рекомендуется реализовать собственный AdsLoader , который будет обертывать сторонний SDK для рекламы, поскольку он обеспечивает преимущества AdsMediaSource , описанные выше. ImaAdsLoader служит примером реализации.

В качестве альтернативы вы можете использовать функцию создания плейлистов в ExoPlayer для формирования последовательности рекламных роликов и видеофрагментов:

Котлин

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

Вставка рекламы на стороне сервера

При вставке рекламы на стороне сервера (также называемой динамической вставкой рекламы, или DAI) медиапоток содержит как рекламу, так и контент. Манифест DASH может указывать как на сегменты контента, так и на сегменты рекламы, возможно, в разных периодах. Для HLS см. документацию Apple по включению рекламы в плейлист .

При использовании серверной вставки рекламы клиенту может потребоваться динамически определять URL-адрес медиафайла для получения объединенного потока, отображать рекламные наложения в пользовательском интерфейсе или отправлять сообщения о событиях в SDK для рекламы или на рекламный сервер.

Компонент DefaultMediaSourceFactory в ExoPlayer может делегировать все эти задачи серверному MediaSource для вставки рекламы по URI, использующим схему ssai:// :

Котлин

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

Библиотека ExoPlayer IMA

Библиотека ExoPlayer IMA предоставляет ImaServerSideAdInsertionMediaSource , что упрощает интеграцию с потоками вставляемой рекламы на стороне сервера IMA в ваше приложение. Она инкапсулирует функциональность SDK IMA DAI для Android и полностью интегрирует предоставленные метаданные рекламы в плеер. Например, это позволяет использовать такие методы, как Player.isPlayingAd() , отслеживать переходы между контентом и рекламой и позволять плееру обрабатывать логику воспроизведения рекламы, например, пропускать уже показанные объявления.

Для использования этого класса необходимо настроить объекты ImaServerSideAdInsertionMediaSource.AdsLoader и ImaServerSideAdInsertionMediaSource.Factory и подключить их к плееру:

Котлин

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

Загрузите ключ ресурса IMA, или идентификатор источника контента и идентификатор видео, создав URL-адрес с помощью ImaServerSideAdInsertionUriBuilder :

Котлин

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

Наконец, освободите загрузчик рекламы, когда он больше не будет использоваться:

Котлин

adsLoader.release()

Java

adsLoader.release();

соображения пользовательского интерфейса

Те же соображения, касающиеся пользовательского интерфейса, что и при вставке рекламы на стороне клиента, применимы и к вставке рекламы на стороне сервера.

Сопутствующие объявления

Некоторые рекламные теги содержат дополнительные сопутствующие объявления, которые могут отображаться в «слотах» в пользовательском интерфейсе приложения. Эти слоты можно передать с помощью метода ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots) . Для получения дополнительной информации см. раздел «Добавление сопутствующих объявлений» .

Использование стороннего SDK для рекламы

Если вам необходимо загружать рекламу с помощью стороннего SDK для рекламы, стоит проверить, предоставляет ли он уже интеграцию с ExoPlayer. Если нет, рекомендуется использовать собственный MediaSource , принимающий URI со схемой ssai:// аналогично ImaServerSideAdInsertionMediaSource .

Фактическую логику создания структуры объявления можно делегировать универсальному компоненту ServerSideAdInsertionMediaSource , который инкапсулирует поток MediaSource и позволяет пользователю устанавливать и обновлять AdPlaybackState , представляющий метаданные объявления.

Часто в рекламные потоки, вставляемые на стороне сервера, содержатся события, привязанные ко времени, которые уведомляют проигрыватель о метаданных рекламы. Информацию о поддерживаемых форматах метаданных можно найти в разделе «Поддерживаемые форматы ». Реализации MediaSource в пользовательском SDK для рекламы могут отслеживать события, привязанные ко времени, от проигрывателя с помощью Player.Listener.onMetadata .