O ExoPlayer reproduz a maioria das transmissões ao vivo adaptáveis imediatamente, sem nenhuma configuração especial. Consulte a página 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 se mover de acordo com o tempo real atual. Isso significa que a posição da reprodução sempre estará em algum lugar nessa janela, na maioria dos casos próxima ao tempo real atual em que o stream está sendo produzido. A diferença entre o tempo real atual e a posição da reprodução é chamada de deslocamento em tempo real.
Como detectar e monitorar reproduções ao vivo
Sempre que uma janela ativa for atualizada, as instâncias Player.Listener
registradas
vão receber um evento onTimelineChanged
. Você pode extrair detalhes sobre a
reprodução ao vivo atual consultando vários métodos Player
e Timeline.Window
, conforme listado abaixo e mostrado na figura abaixo.
Player.isCurrentWindowLive
indica se o item de mídia em reprodução é uma transmissão ao vivo. Esse valor ainda é verdadeiro, mesmo que a transmissão ao vivo tenha terminado.Player.isCurrentWindowDynamic
indica se o item de mídia em reprodução no momento ainda está sendo atualizado. Isso geralmente acontece com transmissões ao vivo que ainda não terminaram. Essa sinalização também é verdadeira para transmissões que não são ao vivo em alguns casos.Player.getCurrentLiveOffset
retorna o deslocamento entre o tempo real atual e a posição da reprodução (se disponível).Player.getDuration
retorna a duração da janela ao vivo atual.Player.getCurrentPosition
retorna a posição de reprodução em relação ao início da janela ao vivo.Player.getCurrentMediaItem
retorna o item de mídia atual, em queMediaItem.liveConfiguration
contém substituições fornecidas pelo app para os parâmetros de ajuste de deslocamento em tempo real e em tempo real.Player.getCurrentTimeline
retorna a estrutura de mídia atual em umTimeline
. OTimeline.Window
atual pode ser recuperado doTimeline
usandoPlayer.getCurrentWindowIndex
eTimeline.getWindow
. NoWindow
:Window.liveConfiguration
contém os parâmetros de ajuste e deslocamento em tempo real desejado. Esses valores são baseados nas informações na mídia e em todas as substituições fornecidas pelo app definidas emMediaItem.liveConfiguration
.Window.windowStartTimeMs
é o tempo desde a era Unix em que a janela ativa é iniciada.Window.getCurrentUnixTimeMs
é o tempo desde a era 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 ao vivo em que o player iniciará a reprodução por padrão.
Procurando em transmissões ao vivo
É possível procurar qualquer lugar na janela ao vivo usando Player.seekTo
. A posição
de busca transmitida é relativa ao início da janela ativa. Por exemplo,
seekTo(0)
buscará o início da janela ativa. O jogador vai tentar
manter o mesmo deslocamento em tempo real da posição de destino após uma busca.
A janela ao vivo também tem uma posição padrão em que a reprodução precisa
ser iniciada. Essa posição geralmente fica em algum lugar perto da borda em tempo real. Procure
a posição padrão chamando Player.seekToDefaultPosition
.
interface de reprodução ao vivo
Os componentes de interface padrão do ExoPlayer mostram a duração da janela ao vivo e
a posição de reprodução atual dentro dela. 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, como mostrar o horário Unix ou o deslocamento em tempo real atual, é possível
bifurcar PlayerControlView
e modificá-lo 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 em relação à borda ativa e o intervalo de velocidades de reprodução que podem ser usadas para ajustar esse deslocamento.
O ExoPlayer recebe valores para esses parâmetros de três lugares, em ordem de prioridade decrescente (o primeiro valor encontrado é usado):
- Valores por
MediaItem
transmitidos paraMediaItem.Builder.setLiveConfiguration
. - Valores padrão globais definidos em
DefaultMediaSourceFactory
. - Os valores são 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 em tempo real desejado. O player tentará se aproximar desse deslocamento em tempo real durante a reprodução, se possível.minOffsetMs
: o deslocamento em tempo real mínimo permitido. Mesmo ao ajustar o deslocamento para as condições atuais da rede, o player não vai tentar ficar abaixo desse deslocamento durante a reprodução.maxOffsetMs
: o deslocamento em tempo real máximo permitido. Mesmo ao ajustar o deslocamento para as condições atuais da rede, o player não tentará ultrapassar esse deslocamento durante a reprodução.minPlaybackSpeed
: a velocidade mínima de reprodução que o player pode usar para voltar ao tentar alcançar o deslocamento em tempo real desejado.maxPlaybackSpeed
: a velocidade máxima de reprodução que o player pode usar para atualizar ao tentar alcançar o deslocamento em tempo real desejado.
Ajuste da velocidade da reprodução
Ao reproduzir uma transmissão ao vivo de baixa latência, o ExoPlayer ajusta o deslocamento ao vivo mudando um pouco a velocidade de reprodução. O player tentará corresponder ao deslocamento em tempo real de destino fornecido pela mídia ou pelo app, mas também tentará reagir às mudanças nas condições da rede. Por exemplo, se ocorrerem novos buffers durante a reprodução, o player vai desacelerar um pouco a reprodução para se afastar da borda ao vivo. Se a rede se tornar estável o suficiente para permitir a reprodução mais perto da borda ativa novamente, o player vai acelerar a reprodução para voltar ao compensação em tempo real de destino.
Se não quiser o ajuste automático de velocidade de reprodução, ele pode ser desativado
configurando as propriedades minPlaybackSpeed
e maxPlaybackSpeed
como 1.0f
.
Da mesma forma, ela pode ser ativada para transmissões ao vivo de não baixa latência configurando
explicitamente com valores 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 de reprodução
Se o ajuste de velocidade estiver ativado, uma LivePlaybackSpeedControl
define os ajustes 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:
fallbackMinPlaybackSpeed
efallbackMaxPlaybackSpeed
: as velocidades mínima e máxima de reprodução que podem ser usadas para ajuste se nem a mídia nem aMediaItem
fornecida pelo app definirem limites.proportionalControlFactor
: controla a fluidez do ajuste de velocidade. Um valor alto torna os ajustes mais repentinos e reativos, mas também aumenta a probabilidade de eles serem audíveis. Um valor menor resulta em uma transição mais suave entre as velocidades, mas fica mais lenta.targetLiveOffsetIncrementOnRebufferMs
: esse valor é adicionado ao deslocamento em tempo real desejado sempre que ocorrer um novo buffer para prosseguir com mais cautela. Esse recurso pode ser desativado definindo o valor como 0.minPossibleLiveOffsetSmoothingFactor
: um fator de suavização exponencial que é usado para rastrear o deslocamento em tempo real mínimo possível 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 às condições aprimoradas da rede, enquanto um valor menor significa que a estimativa será ajustada mais rapidamente, com um risco maior de encontrar novos buffers.
Atrás daLiveWindowException e de ERROR_CODE_ automática - LIVE_WINDOW
A posição de reprodução pode ficar atrasada em relação à janela ao vivo, por exemplo, se o player
estiver pausado ou armazenando em buffer por um período 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 } }