La API de playlist se basa en instancias de MediaItem
, que se pueden compilar de forma conveniente con MediaItem.Builder
. Dentro del reproductor, un MediaItem
se convierte en un MediaSource
reproducible por un MediaSource.Factory
. Sin la configuración personalizada, un DefaultMediaSourceFactory
realiza esta conversión, que es capaz de compilar fuentes multimedia complejas que corresponden a las propiedades del elemento multimedia. A continuación, se describen algunas de las propiedades que se pueden configurar en los elementos multimedia.
Elementos multimedia simples
Un elemento multimedia que solo contenga el URI de transmisión se puede compilar con el método útil fromUri
:
Kotlin
val mediaItem = MediaItem.fromUri(videoUri)
Java
MediaItem mediaItem = MediaItem.fromUri(videoUri);
Para todos los demás casos, se puede usar un MediaItem.Builder
. En el siguiente ejemplo, se compila un elemento multimedia con un ID y algunos metadatos adjuntos:
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();
Adjuntar metadatos puede ser útil para actualizar la IU de tu app cuando se producen transiciones de playlists.
Cómo manejar extensiones de archivo no estándar
ExoPlayer proporciona fuentes de contenido multimedia adaptables para DASH, HLS y SmoothStreaming. Si el URI de ese elemento multimedia adaptable termina con una extensión de archivo estándar, se crea automáticamente la fuente multimedia correspondiente. Si el URI tiene una extensión no estándar o no tiene ninguna extensión, se puede establecer el tipo de MIME de forma explícita para indicar el tipo del elemento multimedia:
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();
Para las transmisiones de contenido multimedia progresivas, no se requiere un tipo de MIME.
Contenido protegido
En el caso del contenido protegido, se deben establecer las propiedades de DRM del elemento multimedia. El UUID es obligatorio; todas las demás propiedades son opcionales.
Una configuración de ejemplo para reproducir un elemento protegido con Widevine DRM en la que el URI de licencia no está disponible directamente en el contenido multimedia (p.ej., en una playlist DASH) y se requieren varias sesiones (p.ej., debido a la rotación de claves):
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();
Dentro del reproductor, DefaultMediaSourceFactory
pasará estas propiedades a un DrmSessionManagerProvider
para obtener un DrmSessionManager
, que luego se insertará en el MediaSource
creado. El comportamiento de la DRM se puede personalizar aún más según tus necesidades.
Transferencia de pistas de subtítulos
Para transferir pistas de subtítulos, se pueden agregar instancias de MediaItem.Subtitle
cuando se compila un elemento multimedia:
Kotlin
val subtitle = 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();
De forma interna, DefaultMediaSourceFactory
usará un MergingMediaSource
para combinar la fuente multimedia de contenido con un SingleSampleMediaSource
para cada pista de subtítulos. DefaultMediaSourceFactory
no admite sideloading de subtítulos para DASH de varios períodos.
Recorta una transmisión de contenido multimedia
Para recortar el contenido al que hace referencia un elemento multimedia, configura posiciones personalizadas de inicio y finalización:
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();
De forma interna, DefaultMediaSourceFactory
usará un ClippingMediaSource
para unir la fuente multimedia del contenido. Existen propiedades de recorte adicionales. Consulta Javadoc de MediaItem.Builder
para obtener más detalles.
Inserción de anuncios
Para insertar anuncios, se debe establecer la propiedad de URI de la etiqueta de anuncio de un elemento multimedia:
Kotlin
val mediaItem = MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build())
Java
MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration(new MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build();
De forma interna, DefaultMediaSourceFactory
unirá la fuente multimedia del contenido en una AdsMediaSource
para insertar anuncios según lo definido por la etiqueta de anuncio. Para que esto funcione, el reproductor también debe tener su DefaultMediaSourceFactory
configurado en consecuencia.