O ExoPlayer reproduz a maioria das transmissões ao vivo adaptáveis sem configuração especial. Consulte a página de formatos compatíveis para mais detalhes.
As transmissões ao vivo adaptáveis oferecem uma janela de mídia disponível que é atualizada em intervalos regulares para acompanhar o tempo real atual. Isso significa que a posição de reprodução sempre estará em algum lugar dessa janela, na maioria dos casos, perto do tempo real atual em que o stream está sendo produzido. A diferença entre a posição atual em tempo real e a posição de reprodução é chamada de deslocamento ao vivo.
Detectar e monitorar reproduções ao vivo
Sempre que uma janela dinâmica é atualizada, as instâncias Player.Listener registradas
recebem um evento onTimelineChanged. É possível recuperar detalhes sobre a
reprodução ao vivo atual consultando vários métodos Player e Timeline.Window, conforme listado abaixo e mostrado na figura a seguir.

Player.isCurrentWindowLiveindica se o item de mídia em reprodução é uma transmissão ao vivo. Esse valor ainda será verdadeiro mesmo que a transmissão ao vivo tenha terminado.Player.isCurrentWindowDynamicindica se o item de mídia em reprodução ainda está sendo atualizado. Isso geralmente é válido para transmissões ao vivo que ainda não terminaram. Essa flag também é verdadeira para transmissões que não são ao vivo em alguns casos.Player.getCurrentLiveOffsetretorna o deslocamento entre o tempo real atual e a posição de reprodução (se disponível).Player.getDurationretorna a duração da janela ao vivo atual.Player.getCurrentPositionretorna a posição de reprodução relativa ao início da janela ao vivo.Player.getCurrentMediaItemretorna o item de mídia atual, em queMediaItem.liveConfigurationcontém substituições fornecidas pelo app para os parâmetros de ajuste e de posição ao vivo de destino.Player.getCurrentTimelineretorna a estrutura de mídia atual em umTimeline. OTimeline.Windowatual pode ser recuperado doTimelineusandoPlayer.getCurrentMediaItemIndexeTimeline.getWindow. NoWindow:Window.liveConfigurationcontém os parâmetros de ajuste de posição ao vivo e posição ao vivo de destino. Esses valores são baseados nas informações da mídia e em substituições fornecidas pelo app definidas emMediaItem.liveConfiguration.Window.windowStartTimeMsé o tempo desde a época do Unix em que a janela de transmissão ao vivo começa.Window.getCurrentUnixTimeMsé o tempo desde a época do Unix do tempo real atual. Esse valor pode ser corrigido por uma diferença de relógio conhecida entre o servidor e o cliente.Window.getDefaultPositionMsé a posição na janela da transmissão ao vivo em que o player vai iniciar a reprodução por padrão.
Como buscar em transmissões ao vivo
Você pode procurar qualquer lugar na janela ao vivo usando Player.seekTo. A posição de busca transmitida é relativa ao início da janela de transmissão ao vivo. Por exemplo, seekTo(0) vai para o início da janela de transmissão ao vivo. O player vai tentar manter o mesmo deslocamento ao vivo da posição procurada após uma busca.
A janela ao vivo também tem uma posição padrão em que a reprodução deve
começar. Essa posição geralmente fica perto da borda ativa. Para buscar a posição padrão, chame Player.seekToDefaultPosition.
Interface de reprodução ao vivo
Os componentes de UI padrão do ExoPlayer mostram a duração da janela ao vivo e
a posição de reprodução atual nela. Isso significa que a posição vai parecer
pular para trás sempre que a janela ao vivo for atualizada. Se você precisar de um comportamento diferente, por exemplo, mostrar o horário Unix ou o deslocamento ao vivo atual, faça um fork de PlayerControlView e modifique-o para atender às suas necessidades.
Como configurar parâmetros de reprodução ao vivo
O ExoPlayer usa alguns parâmetros para controlar o deslocamento da posição de reprodução da borda dinâmica e o intervalo de velocidades de reprodução que podem ser usados para ajustar esse deslocamento.
O ExoPlayer recebe valores para esses parâmetros de três lugares, em ordem decrescente de prioridade (o primeiro valor encontrado é usado):
- Por valores de
MediaItemtransmitidos paraMediaItem.Builder.setLiveConfiguration. - Valores padrão globais definidos em
DefaultMediaSourceFactory. - Valores lidos diretamente da mídia.
Kotlin
// Global settings. val player = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build() // Per MediaItem settings. val mediaItem = MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build() ) .build() player.setMediaItem(mediaItem)
Java
// Global settings. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build(); // Per MediaItem settings. MediaItem mediaItem = new MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()) .build(); player.setMediaItem(mediaItem);
Os valores de configuração disponíveis são:
targetOffsetMs: o deslocamento de destino da transmissão ao vivo. O player tentará se aproximar desse deslocamento ao vivo durante a reprodução, se possível.minOffsetMs: o menor valor de deslocamento ao vivo permitido. Mesmo ao ajustar o deslocamento para as condições atuais da rede, o player não tentará ficar abaixo desse deslocamento durante a reprodução.maxOffsetMs: o deslocamento máximo permitido para transmissões ao vivo. Mesmo ao ajustar o deslocamento para as condições atuais da rede, o player não tentará ficar acima desse deslocamento durante a reprodução.minPlaybackSpeed: a velocidade mínima do vídeo que o player pode usar como alternativa ao tentar alcançar o deslocamento de transmissão ao vivo desejado.maxPlaybackSpeed: a velocidade do vídeo máxima que o player pode usar para alcançar ao tentar atingir o tempo de transmissão ao vivo desejado.
Ajuste da velocidade do vídeo
Ao reproduzir uma transmissão ao vivo de baixa latência, o ExoPlayer ajusta o deslocamento da transmissão mudando um pouco a velocidade do vídeo. O player vai tentar corresponder ao deslocamento ao vivo de destino fornecido pela mídia ou pelo app, mas também vai tentar reagir a condições de rede variáveis. Por exemplo, se ocorrerem rebufferings durante a reprodução, o player vai diminuir um pouco a velocidade para se afastar mais da borda ao vivo. Se a rede ficar estável o suficiente para permitir a reprodução mais próxima da extremidade ativa, o player vai acelerar a reprodução para voltar ao deslocamento ativo desejado.
Se você não quiser o ajuste automático da velocidade do vídeo, desative-o definindo as propriedades minPlaybackSpeed e maxPlaybackSpeed como 1.0f.
Da mesma forma, é possível ativar para transmissões ao vivo sem baixa latência definindo esses valores explicitamente como diferentes de 1.0f. Consulte
a seção de configuração acima para
mais detalhes sobre como essas propriedades podem ser definidas.
Personalizar o algoritmo de ajuste da velocidade do vídeo
Se o ajuste de velocidade estiver ativado, um LivePlaybackSpeedControl vai definir quais ajustes serão feitos. É possível implementar um LivePlaybackSpeedControl personalizado ou personalizar a implementação padrão, que é DefaultLivePlaybackSpeedControl. Em ambos os casos, uma instância pode ser definida ao
criar o player:
Kotlin
val player = ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build() ) .build()
Java
ExoPlayer player = new ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( new DefaultLivePlaybackSpeedControl.Builder() .setFallbackMaxPlaybackSpeed(1.04f) .build()) .build();
Os parâmetros de personalização relevantes de DefaultLivePlaybackSpeedControl são:
fallbackMinPlaybackSpeedefallbackMaxPlaybackSpeed: as velocidades de reprodução mínima e máxima que podem ser usadas para ajuste se nem a mídia nem oMediaItemfornecido pelo app definirem limites.proportionalControlFactor: controla a suavidade do ajuste de velocidade. Um valor alto torna os ajustes mais repentinos e reativos, mas também mais propensos a serem audíveis. Um valor menor resulta em uma transição mais suave entre as velocidades, mas é mais lento.targetLiveOffsetIncrementOnRebufferMs: esse valor é adicionado ao deslocamento dinâmico de destino sempre que ocorre um rebuffer, para prosseguir com mais cautela. Esse recurso pode ser desativado definindo o valor como 0.minPossibleLiveOffsetSmoothingFactor: um fator de suavização exponencial usado para rastrear o menor deslocamento possível em tempo real com base na mídia armazenada em buffer no momento. Um valor muito próximo de 1 significa que a estimativa é mais cautelosa e pode levar mais tempo para se ajustar a condições de rede aprimoradas. Já um valor menor significa que a estimativa será ajustada mais rapidamente, com um risco maior de encontrar rebuffers.
BehindLiveWindowException e ERROR_CODE_BEHIND_LIVE_WINDOW
A posição de reprodução pode ficar atrás da janela ao vivo, por exemplo, se o player
ficar pausado ou em buffer por um período de tempo longo o suficiente. Se isso acontecer, a
reprodução vai falhar, e uma exceção com o código de erro
ERROR_CODE_BEHIND_LIVE_WINDOW será informada por
Player.Listener.onPlayerError. O código do aplicativo pode querer processar esses
erros retomando a reprodução na posição padrão. A PlayerActivity do
app de demonstração exemplifica essa abordagem.
Kotlin
override fun onPlayerError(error: PlaybackException) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition() player.prepare() } else { // Handle other errors } }
Java
@Override public void onPlayerError(PlaybackException error) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition(); player.prepare(); } else { // Handle other errors } }