Skip to content

Playlists & up next

Hand the player a list of videos and it plays them through: when one ends, the next loads automatically — and during the last seconds an “Up next” countdown card appears on the player, which the viewer can tap to skip ahead immediately. Identical API on Android, iOS and web.

Each queue item is a full OGMediaItem, so every item keeps its own pipeline: its own DRM configuration, its own ad schedule, its own subtitles and poster. A postroll on the current item always finishes before the queue advances.

player.loadPlaylist(
listOf(
OGMediaItem.Builder(episode1Url).setTitle("Episode 1").build(),
OGMediaItem.Builder(episode2Url).setTitle("Episode 2").build(),
OGMediaItem.Builder(episode3Url).setTitle("Episode 3").build(),
),
startIndex = 0,
playWhenReady = true,
)

A plain load() clears any queue; retry() after an error keeps it. The current state is always readable: playlist, currentPlaylistIndex (−1 without a playlist) and nextPlaylistItem (nil/null on the last item). skipToNext() jumps to the next item programmatically — it is exactly what the card’s tap calls.

player.addListener(object : PlaybackListener {
override fun onPlaylistItemChanged(index: Int, item: OGMediaItem) {
analytics.track("queue_item", index to item.title)
}
override fun onPlaylistItemSkipped(fromIndex: Int, toIndex: Int) {
analytics.track("queue_skip", fromIndex to toIndex)
}
})

onPlaylistItemChanged fires for the start item, every auto-advance and every skip. onPlaylistItemSkipped fires only when the viewer (or your code) skips via skipToNext() — natural end-of-item advances don’t — so your analytics can tell an impatient skip from a completed view.

By default the card appears during the last 10 seconds of each item (except the last), bottom-right on the player, showing “Next in 5” and counting down. Tapping it skips immediately. Everything about it is configurable — and it can be turned off entirely while the queue keeps advancing silently.

val uiConfig = OGUiConfig.Builder()
.setUpNextLeadSeconds(5) // card window before the end (1–60)
.setUpNextText("{title} starts in {seconds}s…") // your copy, any language
.setUpNextStyle(
backgroundColor = Color(0xE6F6C445),
textStyle = TextStyle(color = Color(0xFF131313), fontSize = 13.sp),
)
// .setShowUpNext(false) // no card; silent advance
.build()

{seconds} and {title} are substituted in the text template. The card is deliberately configuration-only — there is no custom-view slot for it; if you need a fully bespoke surface, drive your own UI from nextPlaylistItem + onProgress and call skipToNext().

Ads are configured per item — each queue entry carries its own tag, so a broadcaster can mix monetized and clean content freely:

player.loadPlaylist(listOf(
OGMediaItem.Builder(ep1).setAdBreaks(AdTagConfig(vmapPrePost)).build(),
OGMediaItem.Builder(ep2).setAdBreaks(AdTagConfig(vastSkippablePreroll)).build(),
OGMediaItem.Builder(trailer).build(), // ad-free
))

The sequencing is broadcaster-grade:

  • An item’s postroll always plays before the queue advances — including when the viewer fast-forwards to the end before the ad schedule has even loaded.
  • The next item’s preroll plays after the advance, so a skip never lands anyone in ad-free content that shouldn’t be.
  • A skip via the card bypasses the current item’s remaining breaks — the onPlaylistItemSkipped callback tells your ad decisioning who skipped.
  • The card never renders over an ad break.
  • Playlists are for VOD sequencing; live items can be queued but never end on their own, so they hold the queue until a skipToNext().
  • The demo apps’ Playlist & up next screen shows every mode side by side — lead time, custom text, branded card, hidden card, and per-item IMA ads.