Preload and cache for faster startup
Short-form feeds, such as reels and episodes, live or die on how fast the next item starts. Arriving at a cold item costs a TLS handshake, a multivariant playlist fetch, a media playlist fetch, and then the first segment: four sequential round trips before a frame can be decoded, and then a decoder still has to start before the first frame appears. The FastPix Android Player SDK gives you four independent levers to cut that delay. Each one is a single setting: you say how much, and the SDK works out the rest. Use as many as fit your feed.
- Fast start tunes buffering so the first frame appears sooner (on by default).
- Preloading prepares the network round trips for upcoming playlist entries before you reach them.
- Disk caching stores what was downloaded so re-watches, scroll-backs, and preloaded entries play from local storage.
- Pre-caching warms items into the cache before a player even exists, for example the rows of a list before one is opened.
- Pre-rendering prepares upcoming entries up to their first frame so moving to them never shows a black screen.
Before you begin
Make sure you have the following:
- The FastPix Android Player SDK version 2.2.2 or later, installed and set up. See Install FastPix Android player and Set up the player.
- A playlist in place if you want preloading or pre-rendering to warm the entries around the current one.
Fast start (on by default)
The player installs a tuned LoadControl, so playback begins after 500 ms of buffered media rather than Media3’s 1000 ms. There’s nothing to configure, but you can tune it or opt out with BufferConfig.
A shallower ahead-buffer is deliberate for feeds: a user who swipes after three seconds never watches the 50 seconds you downloaded, and that is the user’s mobile data.
Preload upcoming entries
PreloadConfig(count, behind) decides how many playlist entries around the current one to prepare ahead of time. Set count for the entries after the current one, and behind for the entries before it.
- Adjacent entries have their first seconds buffered in memory, so they start almost at once.
- Entries further out have their playlists fetched and their tracks chosen, which takes little memory and leaves no round trips before their first segment.
- With the disk cache on, entries further out also have their first segments written to disk, in the rendition this player will pick. The SDK follows the player’s own bitrate cap and bandwidth estimate, so nothing is warmed that playback then refuses.
Cache segments on disk
Disk caching persists what was downloaded, so re-watching, going back, or reaching a preloaded entry reads from disk. Enable it with CacheConfig.
It is safe for any content, live included. FastPix streams are cached by asset: their segment URLs are re-signed on every playlist fetch, so the SDK keys segments by playback ID and rendition rather than by URL. That way a re-watch hits the cache across sessions and token refreshes. Query parameters that only authorize a request (token, signature, expires, cdn) are ignored, while content-selecting parameters stay part of the key.
The cache is process-wide: every player in the app shares one store, and the first config to open it fixes the location and ceiling. Inspect or reset it with MediaCacheProvider.cachedBytes() and MediaCacheProvider.clear().
Opening the cache reads its index from disk. To keep that work off the main thread, open it once at startup from a background thread. Every later call returns the already-open cache.
Since 2.2.1, the cache also keeps HLS playlists while they are safe to reuse, so a cached item can start with no network round trip at all. Only multivariant playlists and finished VOD media playlists are stored, never a live media playlist. Each is served until the earliest signed expires= in it, less 10 minutes, and for at most maxPlaylistAgeMs (24 hours by default). A stream’s playlist is keyed by playback ID, so a copy stored under one host also serves the same stream on stream.fastpix.com or a custom domain. To fetch playlists on every start instead, set maxPlaylistAgeMs to 0.
Pre-cache before a player exists
Preloading and pre-rendering warm the entries around a player that already exists. To warm items before any player is built, such as the rows of a list screen or a feed’s first items at app start, use FastPixPreCacher. The player you build later, with the same CacheConfig, then starts from disk. See Pre-cache videos before a player exists for the full setup.
Pre-render the next frame
Pre-rendering prepares an upcoming entry up to its first frame, so moving to it shows that frame immediately: the first frame is the loader, and there is no black screen while the video starts. Enable it with PrerenderConfig(count, behind), where count covers the entries after the current one and behind covers the entries before it.
One PlayerView moving through a playlist (a player with Next and Previous, or the next episode):
While the current entry plays, the SDK decodes each entry in range in the background and keeps its first frame. On next(), previous(), or skipTo(), the view shows that frame at once and swaps to the video the moment the video’s own first frame is ready. Turn the cache on too, so the background decode and playback share one download.
The counts are a device-limited maximum. Each pre-rendered entry holds a video decoder, and devices run only a few at once, so the SDK pre-renders only as many entries as fit and never refuses the item playing. A pre-render that cannot get a decoder is dropped silently, and the page then loads normally when reached. DRM-protected entries are never pre-rendered.
A page and a PlayerView per entry (reel feeds, carousels) use FastPixPlayerPool, which supplies each page’s player and pre-renders neighboring pages up to their first frame. That shape has its own recipes for ViewPager2, Compose pagers, and RecyclerView. See Build video feeds rather than duplicating the setup here.
Migrating from 2.1.0
The 2.1.0 APIs keep working and are marked deprecated, with IDE quick-fixes to the replacements.
Measure the impact
The sample app ships two working feeds for this purpose. Reel Feed: ViewPager + Compose player is a vertical ViewPager2 whose pages call one shared player composable, with players from FastPixPlayerPool; its heads-up display reports whether each page’s first frame was already on screen when it arrived. Episode Feed is one player over a playlist with Prev and Next and a Preload toggle; its display shows the milliseconds from moving to an entry to that entry’s first frame.
Frequently asked questions
How do I reduce video startup time on Android?
Start with fast-start buffering, which is on by default (playback begins at 500 ms of buffered media). For feeds, add BufferConfig.FEED, preload upcoming entries with PreloadConfig(count = 3), enable disk caching with CacheConfig.enabled(), and pre-render the next entries with PrerenderConfig(count = 1). Together, these remove most of the swipe-to-play delay.
What's the difference between preloading and pre-rendering?
Preloading with PreloadConfig(count, behind) prepares the network work for upcoming playlist entries: playlists fetched, tracks chosen, and, with the cache on, first segments written to disk. Pre-rendering with PrerenderConfig(count, behind) goes one step further and decodes each entry up to its first frame, so moving to it shows that frame with no black screen. They complement each other and are usually enabled together.
Why aren't my cached segments being reused on FastPix?
They are. FastPix streams are cached by playback ID and rendition rather than by URL, so even though FastPix re-signs segment URLs on every playlist fetch, a re-watch still hits the cache across sessions and token refreshes. Just enable CacheConfig.enabled(); the older CacheConfig.forOnDemandFeed() is no longer needed.
Does a shallower buffer risk more rebuffering?
A shallower ahead-buffer (as in BufferConfig.FEED) is a deliberate trade-off for feeds: it saves mobile data a user won’t watch if they swipe away. For general-purpose playback, keep BufferConfig.DEFAULT, or restore Media3’s thresholds with BufferConfig.MEDIA3_DEFAULT.
Why does pre-rendering sometimes not remove the black frame?
Pre-render counts are a device-limited maximum: each pre-rendered entry holds a video decoder, and budget phones run only two or three at once, so the SDK pre-renders only as many as fit. DRM-protected entries are never pre-rendered, and an entry whose own video opens on black still opens on black.
What’s next
- Manage playlists to queue entries that preloading and pre-rendering can warm.
- Build video feeds with
FastPixPlayerPoolfor reels and carousels. - Set the video resize mode so feed items fill the screen.
- Listen to playback events for time, buffering, and error callbacks.