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