17.7 C
New York
Monday, September 8, 2025

Android Builders Weblog: Elevating media playback: Introducing preloading with Media3



Android Builders Weblog: Elevating media playback: Introducing preloading with Media3

Posted by Mayuri Khinvasara Khabya – Developer Relations Engineer (LinkedIn and X)

In at present’s media-centric apps, delivering a clean, uninterrupted playback expertise is essential to a pleasant person expertise. Customers anticipate their movies to begin immediately and play seamlessly with out pauses.

The core problem is latency. Historically, a video participant solely begins its work—connecting, downloading, parsing, buffering—after the person has chosen an merchandise for playback. This reactive method is sluggish for at present’s brief kind video context. The answer is to be proactive. We have to anticipate what the person will watch subsequent and get the content material prepared forward of time. That is the essence of preloading.

The important thing advantages of preloading embrace:

    • 🚀 Sooner Playback Begin: Movies are already able to go, resulting in faster transitions between objects and a extra rapid begin.
    • 📉 Lowered Buffering: By proactively loading knowledge, playback is way much less prone to stall, for instance on account of community hiccups.
    • ✨ Ensuing smoother Person Expertise: The mixture of sooner begins and fewer buffering creates a extra fluid, seamless interplay for customers to take pleasure in.

On this three-part sequence, we’ll introduce and deep dive into Media3’s highly effective utilities for (pre)loading elements.

    • In Half 1, we’ll cowl the foundations: understanding the completely different preloading methods out there in Media3, enabling PreloadConfiguration and organising the DefaultPreloadManager, enabling your app to preload objects. By the tip of this weblog, it’s best to have the ability to preload and play media objects together with your configured rating and period.
    • In Half 2, we’ll get into extra superior subjects of DefaultPreloadManager: utilizing listeners for analytics, exploring production-ready finest practices just like the sliding window sample and customized shared elements of DefaultPreloadManager and ExoPlayer.
    • In Half 3, we’ll dive deep into disk caching with DefaultPreloadManager.

Preloading to the rescue! 🦸‍♀️

The core concept behind preloading is easy: load media content material earlier than you want it. By the point a person swipes to the subsequent video, the primary segments of the video are already downloaded and out there, prepared for rapid playback.

Consider it like a restaurant. A busy kitchen does not look forward to an order to begin chopping onions. 🧅 They do their prep work upfront. Preloading is the prep work on your video participant.

When enabled, preloading can assist decrease be a part of latency when a person skips to the subsequent merchandise earlier than the playback buffer reaches the subsequent merchandise. The primary interval of the subsequent window is ready and video, audio and textual content samples are buffered. The preloaded interval is later queued into the participant with buffered samples instantly out there and able to be fed to the codec for rendering.

In Media3 there are two main APIs for preloading, every suited to completely different use instances. Selecting the best API is step one.

1. Preloading playlist objects with PreloadConfiguration

That is the straightforward method, helpful for linear, sequential media like playlists the place the playback order is predictable (like a sequence of episodes). You give the participant the total listing of media objects utilizing ExoPlayer’s playlist APIs and set the PreloadConfiguration for the participant, then it robotically preloads the subsequent objects within the sequence as configured. This API makes an attempt to optimize the be a part of latency when a person skips to the subsequent merchandise earlier than the playback buffer already overlaps into the subsequent merchandise.

Preloading is barely began when no media is being loaded for the continuing playback, which prevents it from competing for bandwidth with the first playback.

For those who’re nonetheless unsure whether or not you want preloading, this API is a superb low-lift choice to strive it out!

participant.preloadConfiguration =
    PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)

With the PreloadConfiguration above, the participant tries to preload 5 seconds of media for the subsequent merchandise within the playlist.

As soon as opted-in, playlist preloading will be turned off once more through the use of PreloadConfiguration.DEFAULT to disable playlist preloading:

participant.preloadConfiguration = PreloadConfiguration.DEFAULT

2. Preloading dynamic lists with PreloadManager

For dynamic UIs like vertical feeds or carousels, the place the “subsequent” merchandise is decided by person interplay, the PreloadManager API is acceptable. This can be a new highly effective, standalone element throughout the Media3 ExoPlayer library particularly designed to proactively preload. It manages a set of potential MediaSources, prioritizing them primarily based on proximity to the person’s present place and provides granular management over what to preload, appropriate for complicated eventualities like dynamic feeds of brief kind movies.

Setting Up Your PreloadManager

The DefaultPreloadManager is the canonical implementation for PreloadManager.

The builder of DefaultPreloadManager can construct each the DefaultPreloadManager and any ExoPlayer cases that may play its preloaded content material. To create a DefaultPreloadManager, you will want to move a TargetPreloadStatusControl, which the preload supervisor can question to learn how a lot to load for an merchandise. We are going to clarify and outline an instance of TargetPreloadStatusControl within the part beneath.

val preloadManagerBuilder =
DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = val preloadManagerBuilder.construct()

// Construct ExoPlayer with DefaultPreloadManager.Builder
val participant = preloadManagerBuilder.buildExoPlayer()

Utilizing the identical builder for each the ExoPlayer and DefaultPreloadManager is critical, which ensures that the elements below the hood of them are appropriately shared.

And that is it! You now have a supervisor able to obtain directions.

Configuring Length and Rating with TargetPreloadStatusControl

What if you wish to preload, say, 10 seconds of video ? You may present the place of your media objects within the carousel, and the DefaultPreloadManager prioritizes loading the objects primarily based on how shut it’s to the merchandise the person is at present taking part in.

If you wish to management how a lot period of the merchandise to preload, you’ll be able to inform that with DefaultPreloadManager.PreloadStatus you come.

For instance,

    • Merchandise ‘A’ is the best precedence, load 5 seconds of video.
    • Merchandise ‘B’ is medium precedence however while you get to it, load 3 seconds of video.
    • Merchandise ‘C’ is much less precedence, load solely tracks.
    • Merchandise ‘D’ is even much less of a precedence, simply put together.
    • Every other objects are far-off, Don’t preload something.

This granular management can assist you optimize your useful resource utilization which is beneficial for a seamless playback.

import androidx.media3.exoplayer.DefaultPreloadManager.PreloadStatus


class MyTargetPreloadStatusControl(
    currentPlayingIndex: Int = C.INDEX_UNSET
) : TargetPreloadStatusControl<Int,PreloadStatus> {


    // The app is liable for updating this primarily based on UI state
    override enjoyable getTargetPreloadStatus(index: Int): PreloadStatus? {

        val distance = index - currentPlayingIndex

        // Adjoining objects (Subsequent): preload 5 seconds
        if (distance == 1) { 
        // Return a PreloadStatus that's labelled by STAGE_SPECIFIED_RANGE_LOADED and recommend loading // 5000ms from the default begin place
                    return PreloadStatus.specifiedRangeLoaded(5000L)
                } 

        // Adjoining objects (Earlier): preload 3 seconds
        else if (distance == -1) { 
        // Return a PreloadStatus that's labelled by STAGE_SPECIFIED_RANGE_LOADED //and recommend loading 3000ms from the default begin place
                    return PreloadStatus.specifiedRangeLoaded(3000L)
                } 

        // Gadgets two positions away: simply choose tracks
        else if (distance) == 2) {
        // Return a PreloadStatus that's labelled by STAGE_TRACKS_SELECTED
                    return PreloadStatus.TRACKS_SELECTED
                } 

        // Gadgets 4 positions away: simply choose put together
        else if (abs(distance) <= 4) {
        // Return a PreloadStatus that's labelled by STAGE_SOURCE_PREPARED
                    return PreloadStatus.SOURCE_PREPARED
                }

             // All different objects are too far-off
             return null
            }
}

Tip: PreloadManager can hold each the earlier and subsequent objects preloaded, whereas the PreloadConfiguration will solely stay up for the subsequent objects.

Managing Preloading Gadgets

Along with your supervisor created, you can begin telling it what to work on. As your person scrolls via a feed, you will establish the upcoming movies and add them to the supervisor. The interplay with the PreloadManager is a state-driven dialog between your UI and the preloading engine.

1. Add Media Gadgets

As you populate your feed, you have to inform the supervisor of the media it wants to trace. If you’re beginning, you can add the complete listing you wish to preload. Subsequently you’ll be able to hold including a single merchandise to the listing as and when required. You’ve got full management over what objects are within the preloading listing which suggests you additionally need to handle what’s added and faraway from the supervisor.

val initialMediaItems = pullMediaItemsFromService(/* rely= */ 20)
for (index in 0 till initialMediaItems.dimension) {
    preloadManager.add(
        initialMediaItems.get(index),index)
    )
}

The supervisor will now begin fetching knowledge for this MediaItem within the background.

After including, inform the supervisor to re-evaluate its new listing (hinting that one thing has modified like including/ eradicating an merchandise, or the person switches to play a brand new merchandise.)

preloadManager.invalidate()

2. Retrieve and Play an Merchandise

Right here comes the principle playback logic. When the person decides to play that video, you need not create a brand new MediaSource. As an alternative, you ask the PreloadManager for the one it has already ready. You may retrieve the MediaSource from the Preload Supervisor utilizing the MediaItem.

If the retrieved merchandise from the PreloadManager is null, meaning the mediaItem shouldn’t be preloaded but or added to the PreloadMamager, so that you select to set the mediaItem instantly.

// When a media merchandise is about to displ​​ay on the display screen
val mediaSource = preloadManager.getMediaSource(mediaItem)
if (mediaSource!= null) {
  participant.setMediaSource(mediaSource)
} else {
  // If mediaSource is null, that mediaItem hasn't been added but.
  // So, ship it on to the participant.
  participant.setMediaItem(mediaItem)
}
participant.put together()
// When the media merchandise is displaying on the heart of the display screen
participant.play()

By making ready the MediaSource retrieved from the PreloadManager, you seamlessly transition from preloading to playback, utilizing the information that is already in reminiscence. That is what makes the beginning time sooner.

3. Preserve the present index in sync with the UI

Since our feed / listing might be dynamic, it is essential to inform the PreloadManager of your present taking part in index in order that it might at all times prioritize objects nearest to your present index for preloading.

preloadManager.setCurrentPlayingIndex(currentIndex)
// Have to name invalidate() to replace the priorities
preloadManager.invalidate()

4. Take away an Merchandise

To maintain the supervisor environment friendly, it’s best to take away objects it not wants to trace, resembling objects which can be far-off from the person’s present place.

// When an merchandise is simply too removed from the present taking part in index
preloadManager.take away(mediaItem)

If it’s good to clear all objects directly, you’ll be able to name preloadManager.reset().

5. Launch the Supervisor

Whenever you not want the PreloadManager (e.g., when your UI is destroyed), you have to launch it to unencumber its assets. place to do that is the place you’re already releasing your Participant’s assets. It’s beneficial to launch the supervisor earlier than the participant because the participant can proceed to play in the event you do not want any extra preloading.

// In your Exercise's onDestroy() or Composable's onDispose
preloadManager.launch()

Demo time

Verify it stay in motion 👍

Within the demo beneath , we see the impression of PreloadManager on the correct facet which has sooner load occasions, whereas the left facet reveals the present expertise. You can even view the code pattern for the demo. (Bonus: It additionally shows startup latency for each video)

Jetpack Media3 API for fast loading of short videos [PreloadManager]

What’s Subsequent?

And that is a wrap for Half 1! You now have the instruments to construct a dynamic preloading system. You may both use PreloadConfiguration to preload the subsequent merchandise of a playlist in ExoPlayer or arrange a DefaultPreloadManager, add and take away objects on the fly, configure the goal preload standing, and appropriately retrieve the preloaded content material for playback.

In Half 2, we’ll go deeper on the DefaultPreloadManager. We’ll discover hear for preloading occasions, focus on finest practices like utilizing a sliding window to keep away from reminiscence points, and peek below the hood at customized shared elements of ExoPlayer and DefaultPreloadManager.

Do you’ve gotten any suggestions to share? We’re keen to listen to from you.

Keep tuned, and go make your app sooner! 🚀

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Stay Connected

0FansLike
0FollowersFollow
0SubscribersSubscribe
- Advertisement -spot_img

Latest Articles