--- title: Media items --- The [playlist API][] is based on `MediaItem`s, which can be conveniently built using `MediaItem.Builder`. Inside the player, media items are converted into playable `MediaSource`s by a `MediaSource.Factory`. Without [custom configuration]({{ site.baseurl }}/media-sources.html#customizing-media-source-creation), this conversion is carried out by a `DefaultMediaSourceFactory`, which is capable of building complex media sources corresponding to the properties of the media item. Some of the properties that can be set on media items are outlined below. ## Simple media items ## A media item consisting only of the stream URI can be built with the `fromUri` convenience method: ~~~ MediaItem mediaItem = MediaItem.fromUri(videoUri); ~~~ {: .language-java} For all other cases a `MediaItem.Builder` can be used. In the example below, a media item is built with an ID and some attached metadata: ~~~ MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setMediaId(mediaId) .setTag(metadata) .build(); ~~~ {: .language-java} Attaching metadata can be useful for [updating your app's UI]({{ site.baseurl }}/playlists.html#detecting-when-playback-transitions-to-another-media-item) when playlist transitions occur. ## Handling non-standard file extensions The ExoPlayer library provides adaptive media sources for DASH, HLS and SmoothStreaming. If the URI of such an adaptive media item ends with a standard file extension, the corresponding media source is automatically created. If the URI has a non-standard extension or no extension at all, then the MIME type can be set explicitly to indicate the type of the media item: ~~~ // Use the explicit MIME type to build an HLS media item. MediaItem mediaItem = new MediaItem.Builder() .setUri(hlsUri) .setMimeType(MimeTypes.APPLICATION_M3U8) .build(); ~~~ {: .language-java} For progressive media streams a MIME type is not required. ## Protected content ## For protected content, the media item's DRM properties should be set: ~~~ MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setDrmConfiguration( new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) .setLicenseUri(licenseUri) .setMultiSession(true) .setLicenseRequestHeaders(httpRequestHeaders) .build()) .build(); ~~~ {: .language-java} This example builds a media item for Widevine protected content. Inside the player, `DefaultMediaSourceFactory` will pass these properties to a `DrmSessionManagerProvider` to obtain a `DrmSessionManager`, which is then injected into the created `MediaSource`. DRM behaviour can be [further customized]({{ site.baseurl }}/drm.html#using-a-custom-drmsessionmanager) to your needs. ## Sideloading subtitle tracks ## To sideload subtitle tracks, `MediaItem.Subtitle` instances can be added when when building a media item: ~~~ MediaItem.SubtitleConfiguration subtitle = new MediaItem.SubtitleConfiguration.Builder(subtitleUri) .setMimeType(MimeTypes.APPLICATION_SUBRIP) // The correct MIME type (required). .setLanguage(language) // The subtitle language (optional). .setSelectionFlags(selectionFlags) // Selection flags for the track (optional). .build(); MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setSubtitleConfigurations(ImmutableList.of(subtitle)) .build(); ~~~ {: .language-java} Internally, `DefaultMediaSourceFactory` will use a `MergingMediaSource` to combine the content media source with a `SingleSampleMediaSource` for each subtitle track. ## Clipping a media stream ## It's possible to clip the content referred to by a media item by setting custom start and end positions: ~~~ MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setClippingConfiguration( new ClippingConfiguration.Builder() .setStartPositionMs(startPositionMs) .setEndPositionMs(endPositionMs) .build()) .build(); ~~~ {: .language-java} Internally, `DefaultMediaSourceFactory` will use a `ClippingMediaSource` to wrap the content media source. There are additional clipping properties. See the [`MediaItem.Builder` Javadoc][] for more details. When clipping the start of a video file, try to align the start position with a keyframe if possible. If the start position is not aligned with a keyframe then the player will need to decode and discard data from the previous keyframe up to the start position before playback can begin. This will introduce a short delay at the start of playback, including when the player transitions to playing a clipped media source as part of a playlist or due to looping. {:.info} ## Ad insertion ## To insert ads, a media item's ad tag URI property should be set: ~~~ MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build(); ~~~ {: .language-java} Internally, `DefaultMediaSourceFactory` will wrap the content media source in an `AdsMediaSource` to insert ads as defined by the ad tag. For this to work, the the player also needs to have its `DefaultMediaSourceFactory` [configured accordingly]({{ site.baseurl }}/ad-insertion.html#declarative-ad-support). [playlist API]: {{ site.baseurl }}/playlists.html [`MediaItem.Builder` Javadoc]: {{ site.baseurl }}/doc/reference/com/google/android/exoplayer2/MediaItem.Builder.html