Estratégia de Buffering do ExoPlayer

ExoPlayer Version Investigated: 2.9.6

Classes implementando a interface LoadControl definem a estratégia de buffering do ExoPlayer. A estratégia de buffering responde a questões como:

>

  • do precisamos carregar mais dados de mídia?
  • do temos dados de mídia suficientes para iniciar a reprodução?

A estratégia de buffering não é responsável por gerenciar os buffers ou baixar dados de mídia (que é o MediaSource), ou reprodução de dados de mídia (que é o Renderizador). A estratégia de buffering é agnóstica ao formato da mídia sendo reproduzida e tem apenas um papel “consultivo”. Pode acontecer ocasionalmente que o ExoPlayer “pergunte” ao LoadControl se novos dados de mídia devem ser carregados, e ignore a resposta (por exemplo, o ExoPlayer já está no processo de download de dados de mídia).

ExoPlayer vem com uma implementação padrão, DefaultLoadControl. Esta é uma implementação customizável da interface LoadControl.

DefaultLoadControl pode ser usada para configurar, por exemplo :

  • Quantos milissegundos (ms) de dados de mídia o ExoPlayer deve armazenar em buffer antes de iniciar a reprodução (referido como bufferForPlaybackMs). ExoPlayer iniciará a reprodução assim que tiver pelo menos o bufferForPlaybackMs de dados de mídia, mesmo que ExoPlayer não tenha feito o buffer completo do segmento.
  • A quantidade mínima de dados de mídia em buffer (em ms) antes do ExoPlayer começar a carregar mais dados (referidos como minBufferMs).
  • A quantidade máxima de dados de mídia (em ms) ExoPlayer deve armazenar em buffer antes de parar para carregar mais dados (referido como maxBufferMs).
  • Quantos milissegundos de dados de mídia ExoPlayer deve armazenar em buffer antes de reiniciar a reprodução após um evento de rebuffering (referido como bufferForPlaybackAfterRebufferMs).

DefaultLoadControl tem valores padrão para cada uma dessas configurações. Na v2.9.6, estes valores são:

bufferForPlaybackMs

minBufferMs

maxBufferMs

bufferForPlaybackApósRebufferMs

No entanto, os valores variam de versão ExoPlayer para versão. Por exemplo, entre ExoPlayer v2.7.3 e v2.8.0, o maxBufferMs para fluxos de vídeo mudou de 30 segundos para 50 segundos.

A arquitectura modular do ExoPlayer também lhe permite implementar a sua própria estratégia de buffering (que implementa a interface LoadControl) e ligá-la ao ExoPlayer. Mas esse é um tópico para outro post.

Lowering Startup Time

No ExoPlayer, é fácil configurar quantos dados de mídia são necessários antes da reprodução ser iniciada. Na primeira parte desta série de blogs, destacamos a importância do tempo de inicialização como uma métrica de QoE. Um relatório Akamai publicado em 2016 descobriu que “os espectadores começarão a abandonar um vídeo se a inicialização demorar mais de dois segundos para começar a reprodução e para cada segundo adicional de atraso, aproximadamente 6% da audiência sai. com um atraso de 10 segundos, quase metade da audiência saiu”.

ExoPlayer versão 2.9.6 requer por padrão 2.5 segundos de dados media armazenados em buffer antes de iniciar a reprodução. É possível diminuir o tempo de inicialização, exigindo menos dados em buffer. Por um lado, diminuir o valor do buffer de dados de mídia resultaria na redução do tempo de inicialização do vídeo, por mais desvantajoso que seja, isso também poderia resultar no aumento da métrica de rebuffering na inicialização.

Na primeira parte desta série de blogs, usamos um gráfico de radar para visualizar o impacto dos diferentes trade-offs nas 5 métricas de QoE. O gráfico abaixo mostra o impacto de baixar a quantidade mínima necessária de dados de mídia antes de iniciar a reprodução.

aumentando um.pngDesde que o valor padrão para bufferForPlaybackMs de 2,5 segundos é um valor conservador, acreditamos que é uma boa escolha para baixá-lo.

O gráfico abaixo mostra o impacto no tempo de inicialização para um fluxo de 3 Mbps quando se varia o valor desta opção de configuração (não levando em conta o tempo de ida e volta para o servidor, nem se o servidor tem que ir buscar o conteúdo de outro lugar). Por exemplo, em uma conexão de 4 Mbps reproduzindo um fluxo de 3 Mbps, configurar o ExoPlayer para iniciar a reprodução após o buffer de 1,5s de dados de mídia significa que o tempo teórico de inicialização será de 1,1s, ao invés dos 1,9s com a configuração padrão de buffer de 2,5s de dados de mídia.

aumentando dois.pngA próxima seção fala sobre como configurar o ExoPlayer para diminuir o tempo de inicialização e a latência de aceno manual. Se não está familiarizado com o ExoPlayer, recomendamos que primeiro siga o Codelabs on Media streaming do Google com ExoPlayer.

Configurando o DefaultLoadControl

Assumindo que você cria a sua instância ExoPlayer com a implementação padrão LoadControl usando o seguinte código (ou similar):

ExoPlayer player = ExoPlayerFactory.newSimpleInstance(
novo DefaultRenderersFactory(this),
novo DefaultTrackSelector(),
novo DefaultLoadControl())

Pode configurar o DefaultLoadControl usando um DefaultLoadControl.Builder:

/* Instancie um DefaultLoadControl.Builder. */
DefaultLoadControl.Builder builder = novo DefaultLoadControl.Builder();
/* Milissegundos de dados de mídia armazenados em buffer antes que a reprodução seja iniciada ou reiniciada. */
final long loadControlStartBufferMs = 1500;

Configure o novo DefaultLoadControl para usar nossa configuração para quantos Millisegundos de dados de mídia devem ser armazenados em buffer antes do início ou reinício da reprodução após um evento de ação do usuário.

builder.setBufferDurationMs(
DefaultLoadControl.DEFAULT MAX BUFFER MS,
loadControlStartBufferMs,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
/* Constrói a instância real do DefaultLoadControl */
DefaultLoadControl loadControl = builder.createDefaultLoadControl();
/* Instantiate ExoPlayer com o nosso DefaultLoadControl configurado */
ExoPlayer player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(), loadControl);

Lowering Rebuffering Metrics for VOD Content

Besides configurando configurações que levam a um menor tempo de inicialização, você pode configurar o DefaultLoadControl para estabelecer a quantidade de dados de mídia para o buffer, o que pode impactar as métricas de rebuffering para o conteúdo VOD.

ExoPlayer v2.9.6 irá por defeito carregar 50 segundos de dados de media no seu buffer interno se for possível (a configuração maxBufferMs). No caso do conteúdo VOD, aumentar este valor dará ao leitor mais espaço para lidar com as flutuações na largura de banda da rede e baixar as métricas de rebuffering; o lado negativo é que também aumentará o uso de memória do ExoPlayer. Manter o uso de memória baixo é importante em dispositivos de baixo custo. Outra desvantagem é o uso desperdiçado da largura de banda no caso da reprodução parar prematuramente.

Para encontrar o valor que funciona melhor para sua configuração de conteúdo VOD, recomendamos fazer testes A/B com vários valores da opção de configuração para encontrar aquele que dá uma boa troca entre as taxas de rebuffering e o uso de memória. Recomendamos ser conservador, aumentando o valor para, por exemplo 60 segundos inicialmente para descobrir se ele fornece uma diferença material para a métrica de rebuffering.

Configurando o DefaultLoadControl

Abrigamos que você crie sua instância ExoPlayer com a implementação padrão LoadControl (como mostrado na seção anterior em Lowering Startup Time – Configuring the DefaultLoadControl).

Pode configurar o DefaultLoadControl usando um DefaultLoadControl.Builder:

/* Instancie um DefaultLoadControl.Builder. */
DefaultLoadControl.Builder builder = novo
DefaultLoadControl.Builder();
/* Quantidade máxima de dados de mídia para o buffer (em milissegundos). */
final long loadControlMaxBufferMs = 60000;
/*Configure o DefaultLoadControl para usar nossa configuração para quantos
Millisegundos de dados de mídia para o buffer. */
builder.setBufferDurationsMs(
DefaultLoadcontrol.DEFAULT MIN BUFFER MS,
loadControlMaxBufferMs,
/* Para reduzir o tempo de inicialização, altere também a linha abaixo */
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
/* Build the real DefaultLoadControl instance */
DefaultLoadControl loadControl = builder.createDefaultLoadControl();
/* Instantiate ExoPlayer com o nosso DefaultLoadControl configurado */
ExoPlayer player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(),
loadControl);

No caso de minBufferMs e maxBufferMs terem valores diferentes, o ExoPlayer terá um comportamento de explosão recarregando o buffer. ExoPlayer irá fazer o buffer até encher seu buffer com maxBufferMs de dados de mídia, então espere até que ele diminua para minBufferMs (principalmente aplicável a VOD). Uma vez que o nível do buffer caia abaixo de minBufferMs de dados de mídia, o ExoPlayer começará a carregar dados de mídia novamente até que tenha um buffer que valha maxBufferMs de dados de mídia. Tal comportamento de explosão pode levar a problemas de rebufferMs. Este é o comportamento padrão no ExoPlayer v2.9.6 e anteriores, já que estes valores diferem. Na v2.9.6, minBufferMs tem um valor padrão de 15000 e maxBufferMs é 50000.

Para reduzir ainda mais as chances de rebuffering, recomendamos manter sempre um buffer grande no ExoPlayer, definindo os minBufferMs com o mesmo valor que maxBufferMs. A equipa do ExoPlayer fez experiências e descobriu que a definição dos minBufferMs para o mesmo valor que os maxBufferMs (e assim alterando o comportamento do buffer de estourar para pingar) reduziu significativamente os eventos de rebuffering, enquanto aumentava apenas ligeiramente o uso da bateria. Na verdade, começando com a v2.10, o ExoPlayer tem para o caso de uso do vídeo o minBufferMs padrão igual a maxBufferMs e ajustado para 50s.

Como configurar o DefaultLoadControl usando um DefaultLoadControl.Builder:

/* Instale um DefaultLoadControl.Builder. */
DefaultLoadControl.Builder builder = new
DefaultLoadControl.Builder();
/* Quantos milissegundos de dados de mídia a serem armazenados em buffer a qualquer momento. */
final long loadControlBufferMs = DefaultloadControl.MAX_BUFFER_MS; /* Isto é 50000 milisegundos no ExoPlayer 2.9.6 */
/* Configure o DefaultLoadControl para usar o mesmo valor para */
builder.setBufferDurationMs(
loadControlBufferMs,
loadControlBufferMs,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);

Sumário

LoadControl é o ponto de entrada para a estratégia de buffering do ExoPlayer. ExoPlayer vem com uma implementação padrão, porém configurável, da interface LoadControl que deve ser suficiente para a maioria dos casos de uso.

Baseado nas discussões até agora, abaixo está uma rápida recapitulação das recomendações:

  1. Para reduzir o tempo de inicialização, baixe o valor do bufferForPlaybackMs; efetivamente, baixando a quantidade mínima de dados de mídia armazenados em buffer antes de iniciar a reprodução. Isto tem a desvantagem de potencialmente aumentar o número de eventos de rebuffering.
  2. Para reduzir as métricas de rebuffering para conteúdo VOD, aumente o valor de maxBufferMs; efetivamente, aumentando a quantidade máxima de dados de mídia armazenados em buffer. Entretanto, tenha em mente que isso pode impactar negativamente os dispositivos de baixo custo.
  3. Para reduzir as métricas de rebuffering, defina minBufferMs e maxBufferMs para o mesmo valor. Isto mudará o comportamento do ExoPlayer de uma explosão para um amortecimento ao estilo de gotejamento.

Gostaríamos de agradecer aos nossos colegas Christian Worm Mortensen e Laust Brock-Nannestad pelo feedback ao escrever este post.

No próximo post do blog, vamos ver a Estratégia de Seleção de Bitrate do ExoPlayer. Fique atento!

Deixe uma resposta

O seu endereço de email não será publicado.