How to get 4 times better re-buffering with drip-feeding technique in ExoPlayer on Android

Luchianenco Filip
4 min readOct 11, 2019

--

The video playback experience is one of the most critical elements of an OTT application. At UI Centric, we continuously work on improving the playback experience and our recent focus was all about decreasing the amount of buffering users experienced while watching videos. We’ve found this often occurs when a video is being played in poor environmental conditions such as a slow or intermittent network connection. This would usually cause the video playback to temporarily stop so it can buffer more video content.

How is buffer being filled up?

ExoPlayer allows us to leverage the following configurations when playing videos:

  • Max Buffer: The maximum duration of media that the player will attempt to buffer, in milliseconds. As soon as the buffer reaches Max Buffer, it will stop filling it up.
  • Min Buffer: The minimum duration of media that the player will attempt to ensure is buffered at all times, in milliseconds.
  • Buffer for Playback: The default duration of media that must be buffered for playback to start or resume following a user action such as a seek, in milliseconds.
  • Buffer for Playback after Rebuffer: The duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds.

To summarize: as soon as the video starts the player will be in buffering state until Buffer for Playback is reached. Then while playing the video, it will tend to fill up the buffer until Max Buffer. After that it will start filling up the buffer when Min Buffer is reached.

Problem

Because the ExoPlayer default Max Buffer is 50 seconds and the default Min Buffer is 15 seconds, the buffer will only start to refill after the amount of buffer drops to 15 seconds. If any adverse network conditions occur during that time, the user would run out of buffer and playback would stop within 15–20 seconds.

Here’s a visual representation of what happens:

The buffer is filled up until Max Buffer is reached, then nothing is being loaded until Min Buffer is reached.

Solution

Create a custom load control which continuously keeps the buffer filled up based on max buffer — a technique called Drip-Feeding.

Here’s how it looks like when we keep the buffer filled up and when the connection drops we have enough buffer to recover.

The key takeaway here is that the buffer grows up to Max Buffer, then as soon as it gets lower than Max Buffer it loads another segment. keeping it filled. This will keep the buffer filled and allow more tolerance for adverse network conditions. As with everything in life, there is a trade-off to be had with Drip-Feeding as well. Implementing Drip-Feeding will increase device battery usage on mobile devices.

The Code

Create a CustomLoadControl which implements LoadControl . Add in the all the code from the DefaultLoadControl. We’re going to do the same thing but slight different. Pay attention to shouldContinueLoading method from DefaultLoadControl it decides whether to continue filling up the buffer or to stop.

We will wrap that up in a method called:

computeIsBuffering(bufferedDurationUs);

Which only computes the isBuffering variable:

Now just update the initial shouldContinueLoading method to use this method to compute isBuffering :

Business Impact

Here are some stats to demonstrate how the re-buffering experience was improved:

LTE: was 1.21%, is 0.69%, 1.75 times better

4G: was 1.61%, is 0.6%, 2.68 times better

3G: was 5.05%, is 1.34%, 3.76 times better

Total Average: was 0.94%, is 0.69%, 1.36 times better

While 4% for 3G might not look like much, but in practice 4% less buffering for 1,000,000 daily views leads to 40,000 less buffering events every day!

This my dear friends, is how you get a happy OTT customer base, reduce the amount of complaints, and hopefully get more customers leaving a positive feedback.

--

--

Luchianenco Filip

Software engineer. Entrepreneur. You can always do a bit more than you think you can do.