DASH

ExoPlayer supports DASH with multiple container formats. Media streams must be demuxed, meaning that video, audio, and text must be defined in distinct AdaptationSetelements in the DASH manifest (CEA-608 is an exception as described in the table below). The contained audio and video sample formats must also be supported (see the sample formatssection for details).

Feature Supported Comments
Containers
FMP4 YES Demuxed streams only
WebM YES Demuxed streams only
Matroska YES Demuxed streams only
MPEG-TS NO No support planned
Closed captions/subtitles
TTML YES Raw, or embedded in FMP4 according to ISO/IEC 14496-30
WebVTT YES Raw, or embedded in FMP4 according to ISO/IEC 14496-30
CEA-608 YES Embedded in FMP4 when signalled using SCTE Accessibility descriptors
CEA-708 YES Embedded in FMP4 when signalled using SCTE Accessibility descriptors
Metadata
EMSG metadata YES Embedded in FMP4
Content protection
Widevine YES "cenc" scheme: API 19+; "cbcs" scheme: API 25+
PlayReady SL2000 YES Android TV, "cenc" scheme only
ClearKey YES API 21+, "cenc" scheme only
Live playback
Regular live playback YES
Ultra low-latency CMAF live playback YES
Common Media Client Data (CMCD) YES Integration Guide

Using MediaItem

To play a DASH stream, you need to depend on the DASH module.

Kotlin

implementation("androidx.media3:media3-exoplayer-dash:1.4.1")

Groovy

implementation"androidx.media3:media3-exoplayer-dash:1.4.1"

You can then create aMediaItemfor a DASH MPD URI and pass it to the player.

Kotlin

// Create a player instance.
valplayer=ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(dashUri))
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayerplayer=newExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(dashUri));
// Prepare the player.
player.prepare();

If your URI doesn't end with.mpd,you can passMimeTypes.APPLICATION_MPD tosetMimeTypeofMediaItem.Builderto explicitly indicate the type of the content.

ExoPlayer will automatically adapt between representations defined in the manifest, taking into account both available bandwidth and device capabilities.

Using DashMediaSource

For more customization options, you can create aDashMediaSourceand pass it directly to the player instead of aMediaItem.

Kotlin

valdataSourceFactory:DataSource.Factory=DefaultHttpDataSource.Factory()
// Create a dash media source pointing to a dash manifest uri.
valmediaSource:MediaSource=
DashMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(dashUri))
// Create a player instance which gets an adaptive track selector by default.
valplayer=ExoPlayer.Builder(context).build()
// Set the media source to be played.
player.setMediaSource(mediaSource)
// Prepare the player.
player.prepare()

Java

DataSource.FactorydataSourceFactory=newDefaultHttpDataSource.Factory();
// Create a dash media source pointing to a dash manifest uri.
MediaSourcemediaSource=
newDashMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(dashUri));
// Create a player instance which gets an adaptive track selector by default.
ExoPlayerplayer=newExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(mediaSource);
// Prepare the player.
player.prepare();

Accessing the manifest

You can retrieve the current manifest by callingPlayer.getCurrentManifest. For DASH you should cast the returned object toDashManifest.The onTimelineChangedcallback ofPlayer.Listeneris also called whenever the manifest is loaded. This will happen once for a on-demand content, and possibly many times for live content. The following code snippet shows how an app can do something whenever the manifest is loaded.

Kotlin

player.addListener(
object:Player.Listener{
overridefunonTimelineChanged(timeline:Timeline,@TimelineChangeReasonreason:Int){
valmanifest=player.currentManifest
if(manifestisDashManifest){
// Do something with the manifest.
}
}
}
)

Java

player.addListener(
newPlayer.Listener(){
@Override
publicvoidonTimelineChanged(
Timelinetimeline,@Player.TimelineChangeReasonintreason){
Objectmanifest=player.getCurrentManifest();
if(manifest!=null){
DashManifestdashManifest=(DashManifest)manifest;
// Do something with the manifest.
}
}
});

Customizing playback

ExoPlayer provides multiple ways for you to tailor playback experience to your app's needs. See theCustomization pagefor examples.