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 medio de un MediaSource.Factory. Sin una configuración personalizada, esta conversión se lleva a cabo con un DefaultMediaSourceFactory, que es capaz de compilar fuentes de medios complejas correspondientes a las propiedades del elemento multimedia. A continuación, se describen algunas de las propiedades que se pueden establecer en los elementos multimedia.
Elementos multimedia simples
Se puede compilar un elemento multimedia que solo consta del URI de la transmisión con el método de conveniencia 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 crea 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 playlist.
Imágenes
La reproducción de imágenes requiere una duración en el elemento multimedia para especificar durante cuánto tiempo se debe mostrar la imagen durante la reproducción. Consulta la página de la guía de Imágenes para obtener más información sobre las Fotos en movimiento y las bibliotecas de carga de imágenes (por ejemplo, Glide).
Kotlin
val mediaItem = MediaItem.Builder().setUri(imageUri).setImageDurationMs(3000).build()
Java
MediaItem mediaItem = new MediaItem.Builder().setUri(imageUri).setImageDurationMs(3_000).build();
Extensiones de archivos no estándar para medios adaptativos
ExoPlayer proporciona fuentes multimedia adaptables para DASH, HLS y SmoothStreaming. Si el URI de un elemento multimedia adaptable de este tipo termina con una extensión de archivo estándar, se crea automáticamente la fuente de medios correspondiente. Si el URI tiene una extensión no estándar o no tiene extensión, el tipo de MIME se puede establecer de forma explícita para indicar el tipo de 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();
No se requiere un tipo de MIME para los flujos de medios progresivos.
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.
A continuación, se muestra un ejemplo de configuración para reproducir un elemento protegido con DRM de Widevine en el que el URI de la licencia no está disponible directamente en el contenido multimedia (p.ej., en una playlist de 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 inyectará en el MediaSource creado. El comportamiento del DRM se puede personalizar aún más según tus necesidades.
Cómo transferir pistas de subtítulos
Para transferir pistas de subtítulos de forma local, se pueden agregar instancias de MediaItem.Subtitle cuando se crea un elemento multimedia:
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();
Internamente, DefaultMediaSourceFactory usará un MergingMediaSource para combinar la fuente de medios de contenido con un SingleSampleMediaSource para cada pista de subtítulos. DefaultMediaSourceFactory no admite la carga lateral de subtítulos para DASH de varios períodos.
Cómo cortar un flujo de medios
Para recortar el contenido al que hace referencia un elemento multimedia, establece posiciones de inicio y finalización personalizadas:
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();
Internamente, DefaultMediaSourceFactory usará un ClippingMediaSource para unir la fuente de medios de contenido. Hay propiedades de recorte adicionales. Consulta el Javadoc de MediaItem.Builder para obtener más detalles.
Inserción de anuncios
Para insertar anuncios, se debe establecer la propiedad URI de etiqueta de anuncio de un elemento multimedia:
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();
Internamente, DefaultMediaSourceFactory encapsulará la fuente de medios de contenido en un AdsMediaSource para insertar anuncios según lo define la etiqueta de anuncio. Para que esto funcione, el reproductor también debe tener su DefaultMediaSourceFactory
configurado de manera adecuada.