Mobile Development 10 min read

Seamless Single‑Player Video and Ad Playback on Android with Media3/ExoPlayer

The Tubi Android team replaced a dual‑player architecture with a single Media3/ExoPlayer instance, achieving smoother video‑ad transitions, reduced buffering, lower error rates, and improved business metrics, while also addressing decoder‑initialization failures, non‑key‑frame ad buffering, and subtitle timing issues.

Bitu Technology
Bitu Technology
Bitu Technology
Seamless Single‑Player Video and Ad Playback on Android with Media3/ExoPlayer

At Tubi, providing a smooth playback experience is a core goal; the Android team recently launched a single‑player solution that seamlessly plays video content and ads, yielding noticeable improvements in both business and QoE metrics.

Previously, two independent players were used—one for content and one for ads—requiring the release of one instance and creation of another during switches, which caused black screens and brief interruptions while the new player downloaded resources and prepared decoders.

Using Media3/ExoPlayer, the team implemented a custom AdsLoader to integrate their ad SDK. ExoPlayer maintains a unified playback session, pre‑loads the next segment, and follows buffering strategies to ensure immediate playback on transition.

The experiment showed significant growth in business indicators (ad impressions, watch time, ad revenue) and playback metrics, including a sharp drop in ExoTimeoutException , reduced ad join time, lower ad‑drop percentage, and fewer content and ad playback errors.

Challenges and Solutions

Decoder‑initialization failures

On Android TV, decoder‑initialization failures spiked when switching from DRM‑protected content to non‑DRM ads. The team mitigated this by creating a custom MediaCodecFactory and RenderersFactory , extending MediaCodec.createAdapter() to increase the thread‑sleep interval after a failure, dramatically reducing error counts.

Brief buffering at non‑key‑frame ad points

When an ad cue falls on a non‑key‑frame, the player must re‑decode from the previous key‑frame, causing a short buffer period. No current solution exists other than a parallel decoder, which is complex and costly.

SRT subtitle issues

Loading .srt subtitles caused video stalls at ad points and occasional subtitle disappearance when a subtitle’s start time exactly matched the previous subtitle’s end time. Setting DefaultMediaSourceFactory.experimentalUseProgressiveMediaSourceForSubtitles = true prevented stalls, while adding a microsecond to each subtitle’s start time avoided disappearance.

Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
if (matcher.matches()) {
  // Modify the startTime = startTime + 1 of the subtitle
  cueTimesUs.add(parseTimecode(matcher, /* groupOffset= */ 1) + 1);
  cueTimesUs.add(parseTimecode(matcher, /* groupOffset= */ 6));
} else {
  Log.w(TAG, "Skipping invalid timing: " + currentLine);
  continue;
}

Conclusion

By adopting a single‑player seamless playback model, Tubi eliminated black screens and buffering during video‑ad transitions on Android, delivering a smoother experience for viewers and measurable gains in key performance indicators.

Androidvideo streamingExoPlayerSeamless PlaybackAd InsertionMedia3Subtitle Handling
Bitu Technology
Written by

Bitu Technology

Bitu Technology is the registered company of Tubi's China team. We are engineers passionate about leveraging advanced technology to improve lives, and we hope to use this channel to connect and advance together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.