valsubtitle=SubtitleConfiguration.Builder(subtitleUri).setMimeType(mimeType)// The correct MIME type (required)..setLanguage(language)// The subtitle language (optional)..setSelectionFlags(selectionFlags)// Selection flags for the track (optional)..build()valmediaItem=MediaItem.Builder().setUri(videoUri).setSubtitleConfigurations(listOf(subtitle)).build()
Java
MediaItem.SubtitleConfigurationsubtitle=newMediaItem.SubtitleConfiguration.Builder(subtitleUri).setMimeType(mimeType)// The correct MIME type (required)..setLanguage(language)// The subtitle language (optional)..setSelectionFlags(selectionFlags)// Selection flags for the track (optional)..build();MediaItemmediaItem=newMediaItem.Builder().setUri(videoUri).setSubtitleConfigurations(ImmutableList.of(subtitle)).build();
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Media items\n\nThe [playlist API](/guide/topics/media/exoplayer/playlists) is based on `MediaItem` instances, which can be conveniently built\nusing `MediaItem.Builder`. Inside the player, a `MediaItem` is converted into\na playable `MediaSource` by a `MediaSource.Factory`. Without\n[custom configuration](/guide/topics/media/exoplayer/media-sources#customizing-media-source-creation),\nthis conversion is carried out by a `DefaultMediaSourceFactory`, which is\ncapable of building complex media sources corresponding to the properties of the\nmedia item. Some of the properties that can be set on media items are outlined\nbelow.\n\nSimple media items\n------------------\n\nA media item consisting only of the stream URI can be built with the `fromUri`\nconvenience method: \n\n### Kotlin\n\n```kotlin\nval mediaItem = MediaItem.fromUri(videoUri)\n```\n\n### Java\n\n```java\nMediaItem mediaItem = MediaItem.fromUri(videoUri);\n```\n\n\u003cbr /\u003e\n\nFor all other cases, a `MediaItem.Builder` can be used. In the following example, a\nmedia item is built with an ID and some attached metadata: \n\n### Kotlin\n\n```kotlin\nval mediaItem = MediaItem.Builder().setMediaId(mediaId).setTag(myAppData).setUri(videoUri).build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder().setMediaId(mediaId).setTag(myAppData).setUri(videoUri).build();\n```\n\n\u003cbr /\u003e\n\nAttaching metadata can be useful for\n[updating your app's UI](/guide/topics/media/exoplayer/playlists#detecting-transitions)\nwhen playlist transitions occur.\n\nImages\n------\n\nPlayback of images requires a duration in the media item to specify for how long\nthe image should be shown during playback. See the\n[Images](/media/media3/exoplayer/images) guide page for more information on\n[Motion Photos](/media/media3/exoplayer/images#motion-photos) and\n[Image Loading Libraries](/media/media3/exoplayer/images#image-loading-libraries)\n(for example, Glide). \n\n### Kotlin\n\n```kotlin\nval mediaItem = MediaItem.Builder().setUri(imageUri).setImageDurationMs(3000).build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder().setUri(imageUri).setImageDurationMs(3_000).build();\n```\n\n\u003cbr /\u003e\n\nNon-standard file extensions for adaptive media\n-----------------------------------------------\n\nExoPlayer provides adaptive media sources for DASH, HLS, and\nSmoothStreaming. If the URI of such an adaptive media item ends with a standard\nfile extension, the corresponding media source is automatically created. If the\nURI has a non-standard extension or no extension at all, then the MIME type can\nbe set explicitly to indicate the type of the media item: \n\n### Kotlin\n\n```kotlin\nval mediaItem = MediaItem.Builder().setUri(hlsUri).setMimeType(MimeTypes.APPLICATION_M3U8).build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder().setUri(hlsUri).setMimeType(MimeTypes.APPLICATION_M3U8).build();\n```\n\n\u003cbr /\u003e\n\nFor progressive media streams a MIME type is not required.\n\nProtected content\n-----------------\n\nFor protected content, the media item's DRM properties should be set. The UUID\nis required, all the other properties are optional.\n\nAn example config for playing an item protected with Widevine DRM where the\nlicense URI is not available directly in the media (e.g. in a DASH playlist) and\nmultiple sessions are required (e.g. due to key rotation): \n\n### Kotlin\n\n```kotlin\nval mediaItem =\n MediaItem.Builder()\n .setUri(videoUri)\n .setDrmConfiguration(\n MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)\n .setLicenseUri(licenseUri)\n .setMultiSession(true)\n .setLicenseRequestHeaders(httpRequestHeaders)\n .build()\n )\n .build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder()\n .setUri(videoUri)\n .setDrmConfiguration(\n new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)\n .setLicenseUri(licenseUri)\n .setMultiSession(true)\n .setLicenseRequestHeaders(httpRequestHeaders)\n .build())\n .build();\n```\n\n\u003cbr /\u003e\n\nInside the\nplayer, `DefaultMediaSourceFactory` will pass these properties to a\n`DrmSessionManagerProvider` to obtain a `DrmSessionManager`, which is then\ninjected into the created `MediaSource`. DRM behaviour can be\n[further customized](/guide/topics/media/exoplayer/drm#using-a-custom-drmsessionmanager)\nto your needs.\n\nSideloading subtitle tracks\n---------------------------\n\nTo sideload subtitle tracks, `MediaItem.Subtitle` instances can be added when\nbuilding a media item: \n\n### Kotlin\n\n```kotlin\nval subtitle =\n SubtitleConfiguration.Builder(subtitleUri)\n .setMimeType(mimeType) // The correct MIME type (required).\n .setLanguage(language) // The subtitle language (optional).\n .setSelectionFlags(selectionFlags) // Selection flags for the track (optional).\n .build()\nval mediaItem =\n MediaItem.Builder().setUri(videoUri).setSubtitleConfigurations(listOf(subtitle)).build()\n```\n\n### Java\n\n```java\nMediaItem.SubtitleConfiguration subtitle =\n new MediaItem.SubtitleConfiguration.Builder(subtitleUri)\n .setMimeType(mimeType) // The correct MIME type (required).\n .setLanguage(language) // The subtitle language (optional).\n .setSelectionFlags(selectionFlags) // Selection flags for the track (optional).\n .build();\nMediaItem mediaItem =\n new MediaItem.Builder()\n .setUri(videoUri)\n .setSubtitleConfigurations(ImmutableList.of(subtitle))\n .build();\n```\n\n\u003cbr /\u003e\n\nInternally, `DefaultMediaSourceFactory` will use a `MergingMediaSource` to\ncombine the content media source with a `SingleSampleMediaSource` for each\nsubtitle track. `DefaultMediaSourceFactory` does not support sideloading\nsubtitles for multi-period DASH.\n\nClipping a media stream\n-----------------------\n\nTo clip the content referred to by a media item, set custom\nstart and end positions: \n\n### Kotlin\n\n```kotlin\nval mediaItem =\n MediaItem.Builder()\n .setUri(videoUri)\n .setClippingConfiguration(\n MediaItem.ClippingConfiguration.Builder()\n .setStartPositionMs(startPositionMs)\n .setEndPositionMs(endPositionMs)\n .build()\n )\n .build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder()\n .setUri(videoUri)\n .setClippingConfiguration(\n new ClippingConfiguration.Builder()\n .setStartPositionMs(startPositionMs)\n .setEndPositionMs(endPositionMs)\n .build())\n .build();\n```\n\n\u003cbr /\u003e\n\nInternally, `DefaultMediaSourceFactory` will use a `ClippingMediaSource` to wrap\nthe content media source. There are additional clipping properties. See the\n[`MediaItem.Builder` Javadoc](/reference/androidx/media3/common/MediaItem.Builder) for more details.\n| **Note:** 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.\n\nAd insertion\n------------\n\nTo insert ads, a media item's ad tag URI property should be set: \n\n### Kotlin\n\n```kotlin\nval mediaItem =\n MediaItem.Builder()\n .setUri(videoUri)\n .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build())\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder()\n .setUri(videoUri)\n .setAdsConfiguration(new MediaItem.AdsConfiguration.Builder(adTagUri).build())\n .build();\n```\n\n\u003cbr /\u003e\n\nInternally, `DefaultMediaSourceFactory` will wrap the content media source in an\n`AdsMediaSource` to insert ads as defined by the ad tag. For this to work, the\nplayer also needs to have its `DefaultMediaSourceFactory`\n[configured accordingly](/guide/topics/media/exoplayer/ad-insertion#declarative-ad-support).\n| **[Known issue #185:](https://github.com/androidx/media/issues/185)** Subtitles, clipping and ad insertion are only supported if you use `DefaultMediaSourceFactory`."]]