API плейлистов основан на экземплярах MediaItem, которые можно легко создать с помощью MediaItem.Builder. В проигрывателе MediaItem преобразуется в воспроизводимый MediaSource с помощью MediaSource.Factory. Без специальной конфигурации преобразование выполняется с помощью DefaultMediaSourceFactory, который может создавать сложные источники медиаконтента, соответствующие свойствам медиаобъекта. Ниже перечислены некоторые свойства, которые можно задать для медиаконтента.
Простые мультимедийные объекты
Медиаобъект, состоящий только из URI потока, можно создать с помощью fromUriудобного метода:
Kotlin
val mediaItem = MediaItem.fromUri(videoUri)
Java
MediaItem mediaItem = MediaItem.fromUri(videoUri);
Во всех остальных случаях можно использовать MediaItem.Builder. В примере ниже показано, как создать медиаобъект с идентификатором и прикрепленными метаданными:
Kotlin
val mediaItem = MediaItem.Builder().setMediaId(mediaId).setTag(myAppData).setUri(videoUri).build()
Java
MediaItem mediaItem = new MediaItem.Builder().setMediaId(mediaId).setTag(myAppData).setUri(videoUri).build();
Метаданные могут быть полезны для обновления интерфейса приложения при переходе к следующему треку в плейлисте.
Изображения
Для воспроизведения изображений в медиаобъекте должна быть указана продолжительность показа изображения. Подробнее о живых фотографиях и библиотеках для загрузки изображений (например, Glide) рассказывается в руководстве Изображения.
Kotlin
val mediaItem = MediaItem.Builder().setUri(imageUri).setImageDurationMs(3000).build()
Java
MediaItem mediaItem = new MediaItem.Builder().setUri(imageUri).setImageDurationMs(3_000).build();
Нестандартные расширения файлов для адаптивного медиаконтента
ExoPlayer предоставляет адаптивные источники мультимедиа для DASH, HLS и SmoothStreaming. Если URI такого адаптивного медиаконтента заканчивается стандартным расширением файла, соответствующий источник медиаконтента создается автоматически. Если у URI нестандартное расширение или оно отсутствует, MIME-тип можно задать явно, чтобы указать тип медиаобъекта:
Kotlin
val mediaItem = MediaItem.Builder().setUri(hlsUri).setMimeType(MimeTypes.APPLICATION_M3U8).build()
Java
MediaItem mediaItem = new MediaItem.Builder().setUri(hlsUri).setMimeType(MimeTypes.APPLICATION_M3U8).build();
Для прогрессивных медиапотоков MIME-тип не требуется.
Защищенный контент
Для защищенного контента необходимо задать свойства DRM медиаобъекта. UUID обязателен, остальные свойства необязательны.
Пример конфигурации для воспроизведения контента, защищенного с помощью Widevine DRM, если URI лицензии недоступен непосредственно в медиафайле (например, в плейлисте DASH) и требуется несколько сеансов (например, из-за ротации ключей):
Kotlin
val mediaItem = MediaItem.Builder() .setUri(videoUri) .setDrmConfiguration( MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) .setLicenseUri(licenseUri) .setMultiSession(true) .setLicenseRequestHeaders(httpRequestHeaders) .build() ) .build()
Java
MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setDrmConfiguration( new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) .setLicenseUri(licenseUri) .setMultiSession(true) .setLicenseRequestHeaders(httpRequestHeaders) .build()) .build();
Внутри проигрывателя DefaultMediaSourceFactory передаст эти свойства элементу DrmSessionManagerProvider, чтобы получить DrmSessionManager, который затем будет добавлен в созданный элемент MediaSource. Поведение DRM можно настроить в соответствии с вашими потребностями.
Как загрузить дорожки субтитров
Чтобы загрузить дорожки субтитров, при создании медиаконтента можно добавить экземпляры MediaItem.Subtitle:
Kotlin
val subtitle = MediaItem.SubtitleConfiguration.Builder(subtitleUri) .setMimeType(mimeType) // The correct MIME type (required). .setLanguage(language) // The subtitle language (optional). .setSelectionFlags(selectionFlags) // Selection flags for the track (optional). .build() val mediaItem = MediaItem.Builder().setUri(videoUri).setSubtitleConfigurations(listOf(subtitle)).build()
Java
MediaItem.SubtitleConfiguration subtitle = new MediaItem.SubtitleConfiguration.Builder(subtitleUri) .setMimeType(mimeType) // The correct MIME type (required). .setLanguage(language) // The subtitle language (optional). .setSelectionFlags(selectionFlags) // Selection flags for the track (optional). .build(); MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setSubtitleConfigurations(ImmutableList.of(subtitle)) .build();
Внутри DefaultMediaSourceFactory будет использовать MergingMediaSource, чтобы объединить источник медиаконтента с SingleSampleMediaSource для каждой дорожки субтитров. DefaultMediaSourceFactory не поддерживает загрузку субтитров для DASH с несколькими периодами.
Как вырезать фрагмент из медиапотока
Чтобы вырезать фрагмент контента, на который ссылается медиаобъект, задайте собственные начальную и конечную позиции:
Kotlin
val mediaItem = MediaItem.Builder() .setUri(videoUri) .setClippingConfiguration( MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(startPositionMs) .setEndPositionMs(endPositionMs) .build() ) .build()
Java
MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setClippingConfiguration( new ClippingConfiguration.Builder() .setStartPositionMs(startPositionMs) .setEndPositionMs(endPositionMs) .build()) .build();
Внутренне DefaultMediaSourceFactory будет использовать ClippingMediaSource для обертывания источника медиаконтента. Существуют дополнительные свойства обрезки. Подробная информация приведена в документации Javadoc для MediaItem.Builder.
Вставка объявлений
Чтобы вставлять объявления, необходимо задать свойство URI тега объявления для медиаконтента:
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();
Внутренне DefaultMediaSourceFactory будет оборачивать источник медиаконтента в тег AdsMediaSource, чтобы вставлять объявления, определенные тегом объявления. Чтобы это работало, в проигрывателе также должна быть DefaultMediaSourceFactory, настроенная соответствующим образом.