1--- 2title: Media items 3--- 4 5The [playlist API][] is based on `MediaItem`s, which can be conveniently built 6using `MediaItem.Builder`. Inside the player, media items are converted into 7playable `MediaSource`s by a `MediaSource.Factory`. Without 8[custom configuration]({{ site.baseurl }}/media-sources.html#customizing-media-source-creation), 9this conversion is carried out by a `DefaultMediaSourceFactory`, which is 10capable of building complex media sources corresponding to the properties of the 11media item. Some of the properties that can be set on media items are outlined 12below. 13 14## Simple media items ## 15 16A media item consisting only of the stream URI can be built with the `fromUri` 17convenience method: 18 19~~~ 20MediaItem mediaItem = MediaItem.fromUri(videoUri); 21~~~ 22{: .language-java} 23 24For all other cases a `MediaItem.Builder` can be used. In the example below, a 25media item is built with an ID and some attached metadata: 26 27~~~ 28MediaItem mediaItem = new MediaItem.Builder() 29 .setUri(videoUri) 30 .setMediaId(mediaId) 31 .setTag(metadata) 32 .build(); 33~~~ 34{: .language-java} 35 36Attaching metadata can be useful for 37[updating your app's UI]({{ site.baseurl }}/playlists.html#detecting-when-playback-transitions-to-another-media-item) 38when playlist transitions occur. 39 40## Handling non-standard file extensions 41 42The ExoPlayer library provides adaptive media sources for DASH, HLS and 43SmoothStreaming. If the URI of such an adaptive media item ends with a standard 44file extension, the corresponding media source is automatically created. If the 45URI has a non-standard extension or no extension at all, then the MIME type can 46be set explicitly to indicate the type of the media item: 47 48~~~ 49// Use the explicit MIME type to build an HLS media item. 50MediaItem mediaItem = new MediaItem.Builder() 51 .setUri(hlsUri) 52 .setMimeType(MimeTypes.APPLICATION_M3U8) 53 .build(); 54~~~ 55{: .language-java} 56 57For progressive media streams a MIME type is not required. 58 59## Protected content ## 60 61For protected content, the media item's DRM properties should be set: 62 63~~~ 64MediaItem mediaItem = new MediaItem.Builder() 65 .setUri(videoUri) 66 .setDrmConfiguration( 67 new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) 68 .setLicenseUri(licenseUri) 69 .setMultiSession(true) 70 .setLicenseRequestHeaders(httpRequestHeaders) 71 .build()) 72 .build(); 73~~~ 74{: .language-java} 75 76This example builds a media item for Widevine protected content. Inside the 77player, `DefaultMediaSourceFactory` will pass these properties to a 78`DrmSessionManagerProvider` to obtain a `DrmSessionManager`, which is then 79injected into the created `MediaSource`. DRM behaviour can be 80[further customized]({{ site.baseurl }}/drm.html#using-a-custom-drmsessionmanager) 81to your needs. 82 83## Sideloading subtitle tracks ## 84 85To sideload subtitle tracks, `MediaItem.Subtitle` instances can be added when 86when building a media item: 87 88~~~ 89MediaItem.SubtitleConfiguration subtitle = 90 new MediaItem.SubtitleConfiguration.Builder(subtitleUri) 91 .setMimeType(MimeTypes.APPLICATION_SUBRIP) // The correct MIME type (required). 92 .setLanguage(language) // The subtitle language (optional). 93 .setSelectionFlags(selectionFlags) // Selection flags for the track (optional). 94 .build(); 95MediaItem mediaItem = 96 new MediaItem.Builder() 97 .setUri(videoUri) 98 .setSubtitleConfigurations(ImmutableList.of(subtitle)) 99 .build(); 100~~~ 101{: .language-java} 102 103Internally, `DefaultMediaSourceFactory` will use a `MergingMediaSource` to 104combine the content media source with a `SingleSampleMediaSource` for each 105subtitle track. 106 107## Clipping a media stream ## 108 109It's possible to clip the content referred to by a media item by setting custom 110start and end positions: 111 112~~~ 113MediaItem mediaItem = 114 new MediaItem.Builder() 115 .setUri(videoUri) 116 .setClippingConfiguration( 117 new ClippingConfiguration.Builder() 118 .setStartPositionMs(startPositionMs) 119 .setEndPositionMs(endPositionMs) 120 .build()) 121 .build(); 122~~~ 123{: .language-java} 124 125Internally, `DefaultMediaSourceFactory` will use a `ClippingMediaSource` to wrap 126the content media source. There are additional clipping properties. See the 127[`MediaItem.Builder` Javadoc][] for more details. 128 129When clipping the start of a video file, try to align the start position with a 130keyframe if possible. If the start position is not aligned with a keyframe then 131the player will need to decode and discard data from the previous keyframe up to 132the start position before playback can begin. This will introduce a short delay 133at the start of playback, including when the player transitions to playing a 134clipped media source as part of a playlist or due to looping. 135{:.info} 136 137## Ad insertion ## 138 139To insert ads, a media item's ad tag URI property should be set: 140 141~~~ 142MediaItem mediaItem = new MediaItem.Builder() 143 .setUri(videoUri) 144 .setAdsConfiguration( 145 new MediaItem.AdsConfiguration.Builder(adTagUri).build()) 146 .build(); 147~~~ 148{: .language-java} 149 150Internally, `DefaultMediaSourceFactory` will wrap the content media source in an 151`AdsMediaSource` to insert ads as defined by the ad tag. For this to work, the 152the player also needs to have its `DefaultMediaSourceFactory` 153[configured accordingly]({{ site.baseurl }}/ad-insertion.html#declarative-ad-support). 154 155[playlist API]: {{ site.baseurl }}/playlists.html 156[`MediaItem.Builder` Javadoc]: {{ site.exo_sdk }}/MediaItem.Builder.html 157