Usar pistas multimedia

MediaTrack representa una pista multimedia, que puede ser una transmisión de audio o de video, o un texto (como subtítulos o subtítulos opcionales). Tu app puede agrupar, diseñar y activar pistas multimedia.

Configurar un recorrido

Puedes configurar un seguimiento y asignarle un ID único. Con el siguiente código, se crea una pista de texto en inglés, una en francés y en audio, cada una con su propio ID:

Kotlin
val englishSubtitle = MediaTrack.Builder(1 /* ID */, MediaTrack.TYPE_TEXT)
    .setName("English Subtitle")
    .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
    .setContentId("https://some-url/caption_en.vtt")
    /* language is required for subtitle type but optional otherwise */
    .setLanguage("en-US")
    .build()

val frenchSubtitle = MediaTrack.Builder(2, MediaTrack.TYPE_TEXT)
    .setName("French Subtitle")
    .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
    .setContentId("https://some-url/caption_fr.vtt")
    .setLanguage("fr")
    .build()

val frenchAudio = MediaTrack.Builder(3, MediaTrack.TYPE_AUDIO)
    .setName("French Audio")
    .setContentId("trk0001")
    .setLanguage("fr")
    .build()
Java
MediaTrack englishSubtitle = new MediaTrack.Builder(1 /* ID */,
MediaTrack.TYPE_TEXT)
  .setName("English Subtitle")
  .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
  .setContentId("https://some-url/caption_en.vtt")
  /* language is required for subtitle type but optional otherwise */
  .setLanguage("en-US")
  .build();

MediaTrack frenchSubtitle = new MediaTrack.Builder(2, MediaTrack.TYPE_TEXT)
  .setName("French Subtitle")
  .setSubtype(MediaTrack.SUBTYPE_SUBTITLES)
  .setContentId("https://some-url/caption_fr.vtt")
  .setLanguage("fr")
  .build();

MediaTrack frenchAudio = new MediaTrack.Builder(3, MediaTrack.TYPE_AUDIO)
  .setName("French Audio")
  .setContentId("trk0001")
  .setLanguage("fr")
  .build();

Pistas grupales

Puedes agrupar varias pistas en un elemento multimedia, que se representa con MediaInfo. Una instancia de MediaInfo toma un arreglo de pistas y agrega otra información sobre el elemento multimedia. Sobre la base del ejemplo, tu app puede agregar esas tres pistas multimedia a un elemento multimedia pasando una lista de esas tres pistas a MediaInfo.Builder.setMediaTracks(List). Tu app necesita asociar las pistas en un MediaInfo de esta manera antes de cargar el contenido multimedia en la app receptora.

Kotlin
val tracks: MutableList<MediaTrack> = ArrayList<MediaTrack>()
tracks.add(englishSubtitle)
tracks.add(frenchSubtitle)
tracks.add(frenchAudio)
val mediaInfo = MediaInfo.Builder(url)
    .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
    .setContentType(getContentType())
    .setMetadata(getMetadata())
    .setMediaTracks(tracks)
    .build()
Java
List tracks = new ArrayList();
tracks.add(englishSubtitle);
tracks.add(frenchSubtitle);
tracks.add(frenchAudio);
MediaInfo mediaInfo = MediaInfo.Builder(url)
  .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
  .setContentType(getContentType())
  .setMetadata(getMetadata())
  .setMediaTracks(tracks)
  .build();

Quitar segmentos

Para quitar todas las pistas del contenido multimedia actual (como desactivar los tres subtítulos en el ejemplo), llama a MediaInfo.Builder.setMediaTracks(List) y pasa una lista de ID vacía.

Actualizar segmentos

Tu app puede activar una o más pistas asociadas con el elemento multimedia (después de cargar el contenido multimedia), llamando a RemoteMediaClient.setActiveMediaTracks(long[]) y pasando los ID de las pistas que se activarán. En este ejemplo, se activan el subtítulo y el audio en francés:

Kotlin
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setActiveMediaTracks(longArrayOf(2, 3))
    .setResultCallback(ResultCallback {
            mediaChannelResult: RemoteMediaClient.MediaChannelResult ->
                if (!mediaChannelResult.status.isSuccess) {
                    Log.e(TAG, "Failed with status code:" +
                            mediaChannelResult.status.statusCode
                    )
                }
    })
Java
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setActiveMediaTracks(new long[]{2, 3})
    .setResultCallback(mediaChannelResult -> {
        if (!mediaChannelResult.getStatus().isSuccess()) {
            Log.e(TAG, "Failed with status code:" +
                    mediaChannelResult.getStatus().getStatusCode());
        }
    });

Cómo dar estilo a las pistas de texto

TextTrackStyle encapsula la información de estilo de una pista de texto. Después de crear o actualizar un elemento TextTrackStyle existente, puedes aplicar ese estilo al elemento multimedia en reproducción actual llamando a RemoteMediaClient.setTextTrackStyle, de la siguiente manera:

Kotlin
// the ID for the French subtitle is '2' and for the French audio '3'
remoteMediaClient.setTextTrackStyle(style)
    .setResultCallback(ResultCallback {
            mediaChannelResult: RemoteMediaClient.MediaChannelResult ->
                if (!mediaChannelResult.status.isSuccess) {
                    Log.e(TAG, "Failed to set the style, status code: " +
                            mediaChannelResult.status.statusCode
                    )
                }
    })
Java
remoteMediaClient.setTextTrackStyle(style)
    .setResultCallback(mediaChannelResult -> {
        if (!mediaChannelResult.getStatus().isSuccess()) {
            Log.e(TAG, "Failed to set the style, status code: " +
                    mediaChannelResult.getStatus().getStatusCode());
        }
    });

Tu app debe permitir que los usuarios actualicen el estilo de las pistas de texto, ya sea mediante la configuración que proporciona el sistema o la propia app. En Android KitKat y versiones posteriores, puedes usar la configuración de subtítulos opcionales en todo el sistema que proporciona el marco de trabajo:

Kotlin
val textTrackStyle = TextTrackStyle.fromSystemSettings(context)
Java
TextTrackStyle textTrackStyle = TextTrackStyle.fromSystemSettings(context);

Para versiones anteriores a KitKat, la llamada anterior mostrará un objeto cuyos campos no están definidos, por lo que debes propagarlos en la app, según las selecciones de los usuarios y algunos valores predeterminados. Puedes definir el estilo de los siguientes elementos de estilo de la pista de texto:

  • Color y opacidad en primer plano (texto)
  • Color de fondo y opacidad
  • Tipo de borde
  • Color de borde
  • Escala de fuente
  • Familia de fuente
  • Estilo de fuente

Por ejemplo, establece el color del texto en rojo (FF) con un 50% de opacidad (80) de la siguiente manera:

Kotlin
textTrackStyle.foregroundColor = Color.parseColor("#80FF0000")
Java
textTrackStyle.setForegroundColor(Color.parseColor("#80FF0000"));

En KitKat y versiones posteriores, debes registrar tu app para recibir una notificación cuando se actualice la configuración de subtítulos opcionales en todo el sistema. Para ello, debes implementar CaptioningManager.CaptioningChangeListener en tu app y registrar este objeto de escucha mediante una llamada:

Kotlin
CaptioningManager.addCaptioningChangeListener(yourChangeListener)
Java
CaptioningManager.addCaptioningChangeListener(yourChangeListener);

Cuando tu app recibe una devolución de llamada que cambió la configuración de los subtítulos, deberás extraer la nueva configuración y actualizar el estilo del subtítulo del texto que se está reproduciendo en ese momento. Para ello, llama a RemoteMediaClient.setTextTrackStyle y pasa el nuevo estilo.

Recibir actualizaciones de estado

Cuando hay varios remitentes conectados al mismo receptor, es importante que cada uno conozca los cambios en el receptor, incluso si esos cambios se iniciaron desde otros remitentes.

Para ello, tu app debe registrar un RemoteMediaClient.Listener y un RemoteMediaClient.ProgressListener.

Si el TextTrackStyle de los medios actuales cambia, todos los remitentes conectados recibirán una notificación a través de los dos objetos de escucha registrados anteriormente. En este caso, el SDK de la app receptora no verifica si el estilo nuevo es diferente del anterior y, además, notifica a todos los remitentes conectados. Sin embargo, si cambia el estado de los seguimientos activos, solo se notificará el RemoteMediaClient.ProgressListener en los remitentes conectados.

Satisface los requisitos de CORS

Para la transmisión de contenido multimedia adaptable, Google Cast requiere la presencia de encabezados CORS, pero incluso las transmisiones de medios mp4 simples requieren CORS si incluyen pistas. Si deseas habilitar las pistas para cualquier medio, debes habilitar el CORS para tus transmisiones de pistas y las transmisiones multimedia. Por lo tanto, si no tienes encabezados CORS disponibles para tus medios mp4 simples en tu servidor y, luego, agregas una pista de subtítulos simple, no podrás transmitir el contenido multimedia, a menos que actualices tu servidor para incluir el encabezado CORS apropiado. Además, debes permitir al menos los siguientes encabezados: Content-Type, Accept-Encoding y Range. Ten en cuenta que los dos últimos encabezados son encabezados adicionales que quizás no necesites.