Selección de pistas

Cuando un elemento multimedia contiene varias pistas, la selección de pistas es el proceso que determina cuáles se eligen para la reproducción. El proceso de selección de pistas se configura con TrackSelectionParameters, que permite especificar muchas restricciones y anulaciones diferentes que influyen en la selección de pistas.

Cómo consultar los segmentos disponibles

Puedes detectar Player.Listener.onTracksChanged para recibir notificaciones sobre los cambios en los segmentos, incluidos los siguientes:

  • Las pistas disponibles se conocen cuando se completa la preparación del elemento multimedia que se está reproduciendo. Ten en cuenta que el reproductor debe preparar un elemento multimedia para saber qué pistas contiene.
  • Las pistas disponibles cambian porque la reproducción pasa de un elemento multimedia a otro.
  • Cambios en los segmentos seleccionados

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTracksChanged(tracks: Tracks) {
      // Update UI using current tracks.
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTracksChanged(Tracks tracks) {
        // Update UI using current tracks.
      }
    });

También puedes consultar las pistas actuales llamando a player.getCurrentTracks(). El objeto Tracks que se devuelve contiene una lista de objetos Tracks.Group, en la que los segmentos dentro de un solo objeto Group presentan el mismo contenido, pero en diferentes formatos.

Como ejemplo de cómo se pueden agrupar los segmentos, considera una reproducción adaptable en la que se proporciona un feed de video principal en cinco tasas de bits y un feed de video alternativo (por ejemplo, un ángulo de cámara diferente en un partido deportivo) en dos tasas de bits. En este caso, habrá dos grupos de pistas de video: uno correspondiente al feed de video principal que contiene cinco pistas y otro para el feed de video alternativo que contiene dos pistas.

Las pistas de audio cuyos idiomas difieren no se agrupan, ya que el contenido en diferentes idiomas no se considera el mismo. Por el contrario, se pueden agrupar las pistas de audio en el mismo idioma que solo difieren en propiedades como la tasa de bits, la frecuencia de muestreo, el recuento de canales, etcétera. Esto también se aplica a los segmentos de texto.

Se puede consultar cada Group para determinar qué pistas se admiten para la reproducción, cuáles están seleccionadas actualmente y qué Format usa cada pista:

Kotlin

for (trackGroup in tracks.groups) {
  // Group level information.
  val trackType = trackGroup.type
  val trackInGroupIsSelected = trackGroup.isSelected
  val trackInGroupIsSupported = trackGroup.isSupported
  for (i in 0 until trackGroup.length) {
    // Individual track information.
    val isSupported = trackGroup.isTrackSupported(i)
    val isSelected = trackGroup.isTrackSelected(i)
    val trackFormat = trackGroup.getTrackFormat(i)
  }
}

Java

for (Tracks.Group trackGroup : tracks.getGroups()) {
  // Group level information.
  @C.TrackType int trackType = trackGroup.getType();
  boolean trackInGroupIsSelected = trackGroup.isSelected();
  boolean trackInGroupIsSupported = trackGroup.isSupported();
  for (int i = 0; i < trackGroup.length; i++) {
    // Individual track information.
    boolean isSupported = trackGroup.isTrackSupported(i);
    boolean isSelected = trackGroup.isTrackSelected(i);
    Format trackFormat = trackGroup.getTrackFormat(i);
  }
}
  • Un segmento es compatible si el objeto Player puede decodificar y renderizar sus muestras. Ten en cuenta que, incluso si se admiten varios grupos de pistas del mismo tipo (por ejemplo, varios grupos de pistas de audio), esto solo significa que se admiten de forma individual y que el reproductor no necesariamente puede reproducirlos al mismo tiempo.
  • Una pista está seleccionada si se eligió para su reproducción según el TrackSelectionParameters actual. Si se seleccionan varias pistas dentro de un grupo de pistas, el reproductor las usa para la reproducción adaptable (por ejemplo, varias pistas de video con diferentes tasas de bits). Ten en cuenta que solo se reproducirá una de estas pistas a la vez.

Cómo modificar los parámetros de selección de pistas

El proceso de selección de pistas se puede configurar con Player.setTrackSelectionParameters. Puedes hacerlo antes y durante la reproducción. En el siguiente ejemplo, se muestra cómo obtener el TrackSelectionParameters actual del reproductor, modificarlo y actualizar el Player con el resultado modificado:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setMaxVideoSizeSd()
    .setPreferredAudioLanguage("hu")
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setMaxVideoSizeSd()
        .setPreferredAudioLanguage("hu")
        .build());

Selección de pistas basada en restricciones

La mayoría de las opciones en TrackSelectionParameters te permiten especificar restricciones, que son independientes de los segmentos que están disponibles. Las restricciones disponibles incluyen las siguientes:

  • Ancho, altura, velocidad de fotogramas y tasa de bits máximos y mínimos del video
  • Recuento y tasa de bits máximos de canales de audio.
  • Tipos de MIME preferidos para audio y video.
  • Son los idiomas de audio preferidos y los indicadores de roles.
  • Son los idiomas de texto preferidos y las marcas de roles.

ExoPlayer usa valores predeterminados razonables para estas restricciones, por ejemplo, restringir la resolución de video al tamaño de la pantalla y preferir el idioma de audio que coincide con el parámetro de configuración de configuración regional del sistema del usuario.

Existen varios beneficios de usar la selección de pistas basada en restricciones en lugar de seleccionar pistas específicas de las que están disponibles:

  • Puedes especificar restricciones antes de saber qué pistas proporciona un elemento multimedia. Esto significa que las restricciones se pueden especificar antes de que el reproductor haya preparado un elemento multimedia, mientras que la selección de pistas específicas requiere que el código de la aplicación espere hasta que se conozcan las pistas disponibles.
  • Las restricciones se aplican a todos los elementos multimedia de una playlist, incluso cuando esos elementos tienen pistas disponibles diferentes. Por ejemplo, se aplicará automáticamente una restricción de idioma de audio preferido para todos los elementos multimedia, incluso si el Format de la pista en ese idioma varía de un elemento multimedia a otro. Esto no sucede cuando se seleccionan pistas específicas, como se describe a continuación.

Cómo seleccionar pistas específicas

Es posible seleccionar pistas específicas con TrackSelectionParameters. Primero, las pistas disponibles actualmente del reproductor se deben consultar con Player.getCurrentTracks. En segundo lugar, una vez que se identifican los segmentos que se deben seleccionar, se pueden establecer en TrackSelectionParameters con un TrackSelectionOverride. Por ejemplo, para seleccionar el primer segmento de un audioTrackGroup específico, haz lo siguiente:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setOverrideForType(
      TrackSelectionOverride(audioTrackGroup.mediaTrackGroup, /* trackIndex= */ 0)
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setOverrideForType(
            new TrackSelectionOverride(
                audioTrackGroup.getMediaTrackGroup(), /* trackIndex= */ 0))
        .build());

Un TrackSelectionOverride solo se aplicará a los elementos multimedia que contengan un TrackGroup que coincida exactamente con el especificado en la anulación. Por lo tanto, es posible que una anulación no se aplique a un elemento multimedia posterior si este contiene pistas diferentes.

Cómo inhabilitar tipos o grupos de pistas

Los tipos de pistas, como video, audio o texto, se pueden inhabilitar por completo con TrackSelectionParameters.Builder.setTrackTypeDisabled. Un tipo de pista inhabilitado se inhabilitará para todos los elementos multimedia:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
        .build());

Como alternativa, es posible evitar la selección de pistas de un TrackGroup específico si se especifica una anulación vacía para ese grupo:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .addOverride(
      TrackSelectionOverride(disabledTrackGroup.mediaTrackGroup, /* trackIndices= */ listOf())
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .addOverride(
            new TrackSelectionOverride(
                disabledTrackGroup.getMediaTrackGroup(),
                /* trackIndices= */ ImmutableList.of()))
        .build());

Cómo personalizar el selector de pistas

La selección de pistas es responsabilidad de un TrackSelector, una instancia del cual se puede proporcionar cada vez que se compila un ExoPlayer y se obtiene más tarde con ExoPlayer.getTrackSelector().

Kotlin

val trackSelector = DefaultTrackSelector(context)
val player = ExoPlayer.Builder(context).setTrackSelector(trackSelector).build()

Java

DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
ExoPlayer player = new ExoPlayer.Builder(context).setTrackSelector(trackSelector).build();

DefaultTrackSelector es un TrackSelector flexible adecuado para la mayoría de los casos de uso. Utiliza el TrackSelectionParameters establecido en Player, pero también proporciona algunas opciones de personalización avanzadas que se pueden especificar en DefaultTrackSelector.ParametersBuilder:

Kotlin

trackSelector.setParameters(
  trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true)
)

Java

trackSelector.setParameters(
    trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true));

Tunelización

El tunneling puede ayudar a reproducir videos de manera eficiente en transmisiones de alta resolución en algunos dispositivos de TV. Consulta la página sobre el consumo de batería para obtener más notas y detalles.

Puedes establecer una preferencia para la reproducción en túnel y habilitarla en los casos en que la combinación de renderizadores y pistas seleccionadas lo admita. Para ello, usa DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true).

Transferencia de audio

La descarga de audio puede ayudar a ahorrar energía, en particular para las reproducciones más largas con la pantalla apagada. Consulta la página de consumo de batería para obtener más notas y detalles.

Puedes establecer preferencias para la reproducción de audio descargado y habilitarla en los casos en que la combinación de renderizadores y pistas seleccionadas lo admita. Para ello, especifica AudioOffloadModePreferences en tu TrackSelectionParameters.

Kotlin

val audioOffloadPreferences =
  AudioOffloadPreferences.Builder()
    .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
    // Add additional options as needed
    .setIsGaplessSupportRequired(true)
    .build()
player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setAudioOffloadPreferences(audioOffloadPreferences)
    .build()

Java

AudioOffloadPreferences audioOffloadPreferences =
    new AudioOffloadPreferences.Builder()
        .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
        // Add additional options as needed
        .setIsGaplessSupportRequired(true)
        .build();
player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setAudioOffloadPreferences(audioOffloadPreferences)
        .build());