Selección de pistas

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

Cómo consultar las pistas disponibles

Puedes escuchar Player.Listener.onTracksChanged para recibir notificaciones sobre 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 debido a la transición de reproducción 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 llamar a player.getCurrentTracks() para consultar los segmentos actuales. El Tracks que se muestra contiene una lista de objetos Tracks.Group, en la que las pistas dentro de un solo Group presentan el mismo contenido, pero en diferentes formatos.

Como ejemplo de cómo se pueden agrupar las pistas, considera una reproducción adaptativa 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 que corresponde 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 igual. 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 tasa de muestreo, la cantidad de canales, etcétera. Esto también se aplica a los subtítulos.

Se puede consultar cada Group para determinar qué segmentos son compatibles con la reproducción, cuáles están seleccionados actualmente y qué Format usa cada segmento:

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 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), solo significa que se admiten de forma individual y que el reproductor no necesariamente puede reproducirlos al mismo tiempo.
  • Una pista se selecciona si se eligió para la 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 adaptativa (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.

Modifica 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 segmentos basada en restricciones

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

  • Ancho, altura, velocidad de fotogramas y tasa de bits máximos y mínimos del video
  • Cantidad máxima de canales de audio y tasa de bits
  • Son los tipos MIME preferidos para video y audio.
  • Idiomas de audio y marcas de roles preferidos
  • Idiomas de texto y marcas de roles preferidos.

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 la configuración regional del sistema del usuario.

Usar la selección de segmentos basada en restricciones en lugar de seleccionar segmentos específicos de los que están disponibles tiene varios beneficios:

  • Puedes especificar restricciones antes de saber qué pistas proporciona un elemento multimedia. Esto significa que se pueden especificar restricciones antes de que el reproductor prepare 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 diferentes pistas disponibles. 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 segmentos específicos, como se describe a continuación.

Cómo seleccionar segmentos específicos

Es posible seleccionar segmentos específicos con TrackSelectionParameters. Primero, se deben consultar las pistas disponibles actualmente del reproductor con Player.getCurrentTracks. En segundo lugar, una vez que se identifican los segmentos que se deben seleccionar, se pueden configurar en TrackSelectionParameters con un TrackSelectionOverride. Por ejemplo, para seleccionar la primera pista 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 ese elemento contiene pistas diferentes.

Cómo inhabilitar tipos o grupos de segmentos

Los tipos de segmentos, 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 especificas 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());

Personaliza el selector de pistas

La selección de segmentos es responsabilidad de un TrackSelector, una instancia de la cual se puede proporcionar cada vez que se compila un ExoPlayer y, luego, se obtiene 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. Usa 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));

Túneles

Puedes habilitar la reproducción en túnel en los casos en que la combinación de renderizadores y segmentos seleccionados lo admita. Para ello, usa DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true).

Transferencia de datos a la tarjeta de audio

Puedes habilitar la reproducción de audio descargado 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());
);