Seleção de faixas

Quando um item de mídia contém várias faixas, a seleção de faixas é o processo que determina quais delas são escolhidas para reprodução. O processo de seleção de faixa é configurado por TrackSelectionParameters, que permite que muitas restrições diferentes e substituições que influenciam a seleção de faixa sejam especificadas.

Consultar as faixas disponíveis

Você pode ouvir Player.Listener.onTracksChanged para receber notificações sobre mudanças nas faixas, incluindo:

  • As faixas disponíveis são conhecidas quando a preparação do item de mídia que está sendo reproduzido é concluída. O player precisa preparar um item de mídia para saber quais faixas ele contém.
  • As faixas disponíveis mudam devido à transição de reprodução de um item de mídia para outro.
  • Mudanças nas faixas selecionadas.

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.
      }
    });

Também é possível consultar as faixas atuais chamando player.getCurrentTracks(). O Tracks retornado contém uma lista de objetos Tracks.Group, em que as faixas em um único Group apresentam o mesmo conteúdo, mas em formatos diferentes.

Como exemplo de como as faixas podem ser agrupadas, considere uma reprodução adaptativa em que um feed de vídeo principal é fornecido em cinco taxas de bits, e um feed de vídeo alternativo (por exemplo, um ângulo de câmera diferente em uma partida esportiva) é fornecido em duas taxas de bits. Nesse caso, haverá dois grupos de faixas de vídeo, um correspondente ao feed de vídeo principal com cinco faixas e outro para o feed de vídeo alternativo com duas faixas.

Faixas de áudio com idiomas diferentes não são agrupadas, porque o conteúdo em diferentes idiomas não é considerado o mesmo. Por outro lado, faixas de áudio no mesmo idioma que só diferem em propriedades como taxa de bits, taxa de amostragem, contagem de canais e assim por diante podem ser agrupadas. Isso também se aplica a faixas de texto.

Cada Group pode ser consultado para determinar quais faixas têm suporte para reprodução, quais estão selecionadas no momento e qual Format cada faixa usa:

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);
  }
}

  • Uma faixa tem suporte se o Player puder decodificar e renderizar os samples. Mesmo que vários grupos de faixas do mesmo tipo (por exemplo, vários grupos de faixas de áudio) sejam compatíveis, isso significa apenas que eles têm suporte individual e o player não necessariamente pode reproduzir todos ao mesmo tempo.
  • Uma faixa é selecionada se ela foi escolhida para reprodução de acordo com o TrackSelectionParameters atual. Se várias faixas em um grupo forem selecionadas, o player vai usar essas faixas para reprodução adaptativa (por exemplo, várias faixas de vídeo com taxas de bits diferentes). Apenas uma dessas faixas será tocada por vez.

Como modificar os parâmetros de seleção de faixa

O processo de seleção de faixas pode ser configurado usando Player.setTrackSelectionParameters. Você pode fazer isso antes e durante a reprodução. O exemplo a seguir demonstra como receber o TrackSelectionParameters atual do jogador, modificá-lo e atualizar o Player com o resultado modificado:

Kotlin

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

Java

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

Seleção de faixas com base em restrições

A maioria das opções em TrackSelectionParameters permite especificar restrições, que são independentes das faixas que estão realmente disponíveis. As restrições disponíveis incluem:

  • Largura, altura, frame rate e taxa de bits máximas e mínimas do vídeo.
  • Contagem máxima de canais de áudio e taxa de bits.
  • Tipos MIME preferidos para vídeo e áudio.
  • Idiomas de áudio e flags de função preferidos.
  • Idiomas de texto e flags de função preferidos.

O ExoPlayer usa padrões razoáveis para essas restrições, por exemplo, restringindo a resolução do vídeo ao tamanho da tela e preferindo o idioma de áudio que corresponde à configuração de localidade do sistema do usuário.

Há vários benefícios em usar a seleção de faixas com restrições em vez de selecionar faixas específicas entre as disponíveis:

  • É possível especificar restrições antes de saber quais faixas um item de mídia oferece. Isso significa que as restrições podem ser especificadas antes que o player prepare um item de mídia, enquanto a seleção de faixas específicas exige que o código do aplicativo aguarde até que as faixas disponíveis sejam conhecidas.
  • As restrições são aplicadas a todos os itens de mídia em uma playlist, mesmo quando eles têm faixas diferentes disponíveis. Por exemplo, uma restrição de idioma de áudio preferencial será aplicada automaticamente a todos os itens de mídia, mesmo que o Format da faixa nesse idioma varie de um item de mídia para outro. Isso não acontece ao selecionar faixas específicas, conforme descrito abaixo.

Como selecionar faixas específicas

É possível selecionar faixas específicas usando TrackSelectionParameters. Primeiro, as faixas disponíveis do player precisam ser consultadas usando Player.getCurrentTracks. Em segundo lugar, depois de identificar quais faixas selecionar, elas podem ser definidas em TrackSelectionParameters usando um TrackSelectionOverride. Por exemplo, para selecionar a primeira faixa de um audioTrackGroup específico:

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());

Um TrackSelectionOverride só será aplicado a itens de mídia que contêm um TrackGroup que corresponde exatamente ao especificado na substituição. Portanto, uma substituição pode não ser aplicada a um item de mídia subsequente se ele tiver faixas diferentes.

Como desativar tipos ou grupos de faixas

Tipos de faixa, como vídeo, áudio ou texto, podem ser desativados completamente usando TrackSelectionParameters.Builder.setTrackTypeDisabled. Um tipo de faixa desativado será desativado para todos os itens de mídia:

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, é possível impedir a seleção de faixas de um TrackGroup específico especificando uma substituição vazia para esse 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());

Personalizar o seletor de faixas

A seleção de faixas é responsabilidade de um TrackSelector, uma instância que pode ser fornecida sempre que um ExoPlayer é criado e depois recebido com 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 é um TrackSelector flexível adequado para a maioria dos casos de uso. Ele usa o TrackSelectionParameters definido no Player, mas também oferece algumas opções de personalização avançada que podem ser especificadas no DefaultTrackSelector.ParametersBuilder:

Kotlin

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

Java

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

Túnel

É possível ativar a reprodução em túnel nos casos em que a combinação de renderizadores e faixas selecionadas oferece suporte a ela. Para fazer isso, use DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true).

Descarregamento de áudio

É possível ativar a reprodução de áudio descarregado nos casos em que a combinação de renderizadores e faixas selecionadas oferece suporte a isso. Para fazer isso, especifique AudioOffloadModePreferences no 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());
);