Seleção de faixas

Quando um item de mídia contém várias faixas, a seleção de faixas é o processo que determina qual delas será escolhida para reprodução. O processo de seleção de faixas é configurado pelo TrackSelectionParameters, o que permite que muitas restrições e substituições diferentes que influenciem a seleção de faixas sejam especificadas.

Como 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 serão conhecidas quando a preparação do item de mídia que está sendo reproduzido for 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 da 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 Track.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) em duas taxas de bits. Nesse caso, haverá dois grupos de faixas de vídeo: um correspondente ao feed de vídeo principal que contém cinco faixas e um segundo para o feed de vídeo alternativo contendo duas faixas.

As faixas de áudio com idiomas diferentes não são agrupadas, porque o conteúdo em idiomas diferentes não é considerado o mesmo. Por outro lado, faixas de áudio no mesmo idioma que diferem apenas em propriedades como taxa de bits, taxa de amostragem e contagem de canais 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 atualmente 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 será compatível se o Player puder decodificar e renderizar as amostras. 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 são compatíveis individualmente e que o player não pode necessariamente reproduzi-los ao mesmo tempo.
  • Uma faixa será selecionada se tiver sido escolhida para reprodução de acordo com o TrackSelectionParameters atual. Se várias faixas de um grupo forem selecionadas, o player vai usar essas faixas para reprodução adaptável, por exemplo, várias faixas de vídeo com diferentes taxas de bits. Apenas uma delas vai ser tocada por vez.

Modificar parâmetros de seleção de faixas

O processo de seleção de faixa pode ser configurado usando Player.setTrackSelectionParameters. É possível fazer isso antes e durante a reprodução. O exemplo abaixo demonstra como acessar o TrackSelectionParameters atual do player, 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 trilha com base em restrições

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

  • Largura, altura, frame rate, taxa de bits e largura de vídeo máxima e mínima 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 preferidos e flags de papéis.
  • Idiomas de texto e flags de função preferidos.

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

Há vários benefícios em usar a seleção de faixas baseada em restrições, em vez de escolher faixas específicas disponíveis:

  • Você pode especificar restrições antes de saber o que rastreia um item de mídia. Isso significa que as restrições podem ser especificadas antes que o jogador preparou 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.
  • 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 vai 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 o próximo. 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 no momento do player precisam ser consultadas usando Player.getCurrentTracks. Em segundo lugar, após identificar quais faixas serão selecionadas, elas podem ser definidas em TrackSelectionParameters usando um TrackSelectionOverride. Por exemplo, para selecionar a primeira faixa de uma audioTrackGroup específica:

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ó é aplicado a itens de mídia que contêm uma TrackGroup que corresponde exatamente ao especificado na substituição. Portanto, uma substituição pode não se aplicar a um item de mídia subsequente se esse item contém faixas diferentes.

Desativar tipos de faixa ou grupos

Tipos de faixa, como vídeo, áudio ou texto, podem ser totalmente desativados 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 evitar 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 recebido posteriormente 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 fornece algumas opções avançadas de personalização que podem ser especificadas no DefaultTrackSelector.ParametersBuilder:

Kotlin

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

Java

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

Encapsulamento

Você pode ativar a reprodução encapsulada quando a combinação de renderizadores e faixas selecionadas for compatível com ela. Para fazer isso, use DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true).

Descarga de áudio

Você pode ativar a reprodução de áudio descarregada quando a combinação de renderizadores e faixas selecionadas oferecer suporte a ela. 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());
);