HLS

O ExoPlayer oferece suporte ao HLS com vários formatos de contêiner. Os formatos de amostra de áudio e vídeo contidos também precisam ser compatíveis (consulte a seção Formatos de amostra para mais detalhes). Recomendamos que os produtores de conteúdo HLS gerem streams HLS de alta qualidade, conforme descrito aqui.

Recurso Compatível Comentários
Contêineres
MPEG-TS SIM
FMP4/CMAF SIM
ADTS (AAC) SIM
MP3 SIM
Legendas/closed captions
CEA-608 SIM
CEA-708 SIM
WebVTT SIM
Metadados
ID3 SIM
SCTE-35 NÃO
Proteção de conteúdo
AES-128 SIM
Exemplo de AES-128 NÃO
Widevine SIM API 19+ (esquema "cenc") e 25+ (esquema "cbcs")
PlayReady SL2000 SIM Somente no Android TV
Controle do servidor
Atualizações delta SIM
Bloquear a recarga da playlist SIM
Bloquear o carregamento de dicas de pré-carregamento SIM Exceto para byteranges com comprimentos indefinidos
Reprodução ao vivo
Reprodução ao vivo normal SIM
HLS de baixa latência (Apple) SIM
HLS de baixa latência (Comunidade) NÃO
Dados comuns do cliente de mídia (CMCD, na sigla em inglês) SIM Guia de integração

Como usar o MediaItem

Para reproduzir uma transmissão HLS, você precisa depender do módulo HLS.

Kotlin

implementation("androidx.media3:media3-exoplayer-hls:1.5.0")

Groovy

implementation "androidx.media3:media3-exoplayer-hls:1.5.0"

Em seguida, crie um MediaItem para um URI de playlist HLS e transmita-o ao reprodutor.

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri))
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri));
// Prepare the player.
player.prepare();

Se o URI não terminar com .m3u8, você poderá transmitir MimeTypes.APPLICATION_M3U8 para setMimeType de MediaItem.Builder para indicar explicitamente o tipo de conteúdo.

O URI do item de mídia pode apontar para uma playlist de mídia ou uma playlist multivariante. Se o URI apontar para uma playlist com várias variantes que declara várias tags #EXT-X-STREAM-INF, o ExoPlayer vai se adaptar automaticamente entre as variantes, levando em conta a largura de banda disponível e os recursos do dispositivo.

Como usar o HlsMediaSource

Para mais opções de personalização, crie uma HlsMediaSource e transmita-a diretamente ao player em vez de uma MediaItem.

Kotlin

// Create a data source factory.
val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory()
// Create a HLS media source pointing to a playlist uri.
val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri))
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri));
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource);
// Prepare the player.
player.prepare();

Como acessar o manifesto

É possível extrair o manifesto atual chamando Player.getCurrentManifest. Para HLS, você precisa transmitir o objeto retornado para HlsManifest. O callback onTimelineChanged de Player.Listener também é chamado sempre que o manifesto é carregado. Isso vai acontecer uma vez para conteúdo on demand e talvez muitas vezes para conteúdo ao vivo. O snippet de código a seguir mostra como um app pode fazer algo sempre que o manifesto é carregado.

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
      val manifest = player.currentManifest
      if (manifest is HlsManifest) {
        // Do something with the manifest.
      }
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTimelineChanged(
          Timeline timeline, @Player.TimelineChangeReason int reason) {
        Object manifest = player.getCurrentManifest();
        if (manifest != null) {
          HlsManifest hlsManifest = (HlsManifest) manifest;
          // Do something with the manifest.
        }
      }
    });

Como personalizar a reprodução

O ExoPlayer oferece várias maneiras de personalizar a experiência de reprodução de acordo com as necessidades do app. Consulte a página de personalização para conferir exemplos.

Como desativar a preparação sem fragmentos

Por padrão, o ExoPlayer vai usar a preparação sem separações em blocos. Isso significa que o ExoPlayer usará apenas as informações na playlist multivariante para preparar o stream, o que funciona se as tags #EXT-X-STREAM-INF contiverem o atributo CODECS.

Talvez seja necessário desativar esse recurso se os segmentos de mídia contiverem faixas de legenda munidas que não forem declaradas na playlist multivariante com uma tag #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS. Caso contrário, essas faixas de legenda não serão detectadas e reproduzidas. É possível desativar a preparação sem blocos no HlsMediaSource.Factory, conforme mostrado no snippet abaixo. Isso vai aumentar o tempo de inicialização, já que o ExoPlayer precisa fazer o download de um segmento de mídia para descobrir essas faixas adicionais. É preferível declarar as faixas de legenda na playlist de variantes múltiplas.

Kotlin

val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory)
    .setAllowChunklessPreparation(false)
    .createMediaSource(MediaItem.fromUri(hlsUri))

Java

HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory)
        .setAllowChunklessPreparation(false)
        .createMediaSource(MediaItem.fromUri(hlsUri));

Criar conteúdo HLS de alta qualidade

Para aproveitar ao máximo o ExoPlayer, siga algumas diretrizes para melhorar seu conteúdo HLS. Leia nossa postagem no Medium sobre a reprodução de HLS no ExoPlayer para uma explicação completa. Os pontos principais são:

  • Use durações precisas dos segmentos.
  • Use uma transmissão de mídia contínua. Evite mudanças na estrutura de mídia em segmentos.
  • Use a tag #EXT-X-INDEPENDENT-SEGMENTS.
  • Prefira streams desmultiplexados, em vez de arquivos que incluem vídeo e áudio.
  • Inclua todas as informações possíveis na playlist multivariante.

As seguintes diretrizes se aplicam especificamente a transmissões ao vivo:

  • Use a tag #EXT-X-PROGRAM-DATE-TIME.
  • Use a tag #EXT-X-DISCONTINUITY-SEQUENCE.
  • Ofereça uma janela de longa duração. Um minuto ou mais é ótimo.