xref: /aosp_15_r20/external/exoplayer/tree_15dc86382f17a24a3e881e52e31a810c1ea44b49/docs/hls.md (revision 30877f796caf59d855b10b687a5d6b3918d765cb)
1*30877f79SAndroid Build Coastguard Worker---
2*30877f79SAndroid Build Coastguard Workertitle: HLS
3*30877f79SAndroid Build Coastguard Worker---
4*30877f79SAndroid Build Coastguard Worker
5*30877f79SAndroid Build Coastguard Worker{% include_relative _page_fragments/supported-formats-hls.md %}
6*30877f79SAndroid Build Coastguard Worker
7*30877f79SAndroid Build Coastguard Worker## Using MediaItem ##
8*30877f79SAndroid Build Coastguard Worker
9*30877f79SAndroid Build Coastguard WorkerTo play an HLS stream, you need to depend on the HLS module.
10*30877f79SAndroid Build Coastguard Worker
11*30877f79SAndroid Build Coastguard Worker~~~
12*30877f79SAndroid Build Coastguard Workerimplementation 'com.google.android.exoplayer:exoplayer-hls:2.X.X'
13*30877f79SAndroid Build Coastguard Worker~~~
14*30877f79SAndroid Build Coastguard Worker{: .language-gradle}
15*30877f79SAndroid Build Coastguard Worker
16*30877f79SAndroid Build Coastguard WorkerYou can then create a `MediaItem` for an HLS playlist URI and pass it to the
17*30877f79SAndroid Build Coastguard Workerplayer.
18*30877f79SAndroid Build Coastguard Worker
19*30877f79SAndroid Build Coastguard Worker~~~
20*30877f79SAndroid Build Coastguard Worker// Create a player instance.
21*30877f79SAndroid Build Coastguard WorkerExoPlayer player = new ExoPlayer.Builder(context).build();
22*30877f79SAndroid Build Coastguard Worker// Set the media item to be played.
23*30877f79SAndroid Build Coastguard Workerplayer.setMediaItem(MediaItem.fromUri(hlsUri));
24*30877f79SAndroid Build Coastguard Worker// Prepare the player.
25*30877f79SAndroid Build Coastguard Workerplayer.prepare();
26*30877f79SAndroid Build Coastguard Worker~~~
27*30877f79SAndroid Build Coastguard Worker{: .language-java}
28*30877f79SAndroid Build Coastguard Worker
29*30877f79SAndroid Build Coastguard WorkerIf your URI doesn't end with `.m3u8`, you can pass `MimeTypes.APPLICATION_M3U8`
30*30877f79SAndroid Build Coastguard Workerto `setMimeType` of `MediaItem.Builder` to explicitly indicate the type of the
31*30877f79SAndroid Build Coastguard Workercontent.
32*30877f79SAndroid Build Coastguard Worker
33*30877f79SAndroid Build Coastguard WorkerThe URI of the media item may point to either a media playlist or a multivariant
34*30877f79SAndroid Build Coastguard Workerplaylist. If the URI points to a multivariant playlist that declares multiple
35*30877f79SAndroid Build Coastguard Worker`#EXT-X-STREAM-INF` tags then ExoPlayer will automatically adapt between
36*30877f79SAndroid Build Coastguard Workervariants, taking into account both available bandwidth and device capabilities.
37*30877f79SAndroid Build Coastguard Worker
38*30877f79SAndroid Build Coastguard Worker## Using HlsMediaSource ##
39*30877f79SAndroid Build Coastguard Worker
40*30877f79SAndroid Build Coastguard WorkerFor more customization options, you can create a `HlsMediaSource` and pass it
41*30877f79SAndroid Build Coastguard Workerdirectly to the player instead of a `MediaItem`.
42*30877f79SAndroid Build Coastguard Worker
43*30877f79SAndroid Build Coastguard Worker~~~
44*30877f79SAndroid Build Coastguard Worker// Create a data source factory.
45*30877f79SAndroid Build Coastguard WorkerDataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
46*30877f79SAndroid Build Coastguard Worker// Create a HLS media source pointing to a playlist uri.
47*30877f79SAndroid Build Coastguard WorkerHlsMediaSource hlsMediaSource =
48*30877f79SAndroid Build Coastguard Worker    new HlsMediaSource.Factory(dataSourceFactory)
49*30877f79SAndroid Build Coastguard Worker        .createMediaSource(MediaItem.fromUri(hlsUri));
50*30877f79SAndroid Build Coastguard Worker// Create a player instance.
51*30877f79SAndroid Build Coastguard WorkerExoPlayer player = new ExoPlayer.Builder(context).build();
52*30877f79SAndroid Build Coastguard Worker// Set the media source to be played.
53*30877f79SAndroid Build Coastguard Workerplayer.setMediaSource(hlsMediaSource);
54*30877f79SAndroid Build Coastguard Worker// Prepare the player.
55*30877f79SAndroid Build Coastguard Workerplayer.prepare();
56*30877f79SAndroid Build Coastguard Worker~~~
57*30877f79SAndroid Build Coastguard Worker{: .language-java}
58*30877f79SAndroid Build Coastguard Worker
59*30877f79SAndroid Build Coastguard Worker## Accessing the manifest ##
60*30877f79SAndroid Build Coastguard Worker
61*30877f79SAndroid Build Coastguard WorkerYou can retrieve the current manifest by calling `Player.getCurrentManifest`.
62*30877f79SAndroid Build Coastguard WorkerFor HLS you should cast the returned object to `HlsManifest`. The
63*30877f79SAndroid Build Coastguard Worker`onTimelineChanged` callback of `Player.Listener` is also called whenever
64*30877f79SAndroid Build Coastguard Workerthe manifest is loaded. This will happen once for a on-demand content, and
65*30877f79SAndroid Build Coastguard Workerpossibly many times for live content. The code snippet below shows how an app
66*30877f79SAndroid Build Coastguard Workercan do something whenever the manifest is loaded.
67*30877f79SAndroid Build Coastguard Worker
68*30877f79SAndroid Build Coastguard Worker~~~
69*30877f79SAndroid Build Coastguard Workerplayer.addListener(
70*30877f79SAndroid Build Coastguard Worker    new Player.Listener() {
71*30877f79SAndroid Build Coastguard Worker      @Override
72*30877f79SAndroid Build Coastguard Worker      public void onTimelineChanged(
73*30877f79SAndroid Build Coastguard Worker          Timeline timeline, @Player.TimelineChangeReason int reason) {
74*30877f79SAndroid Build Coastguard Worker        Object manifest = player.getCurrentManifest();
75*30877f79SAndroid Build Coastguard Worker        if (manifest != null) {
76*30877f79SAndroid Build Coastguard Worker          HlsManifest hlsManifest = (HlsManifest) manifest;
77*30877f79SAndroid Build Coastguard Worker          // Do something with the manifest.
78*30877f79SAndroid Build Coastguard Worker        }
79*30877f79SAndroid Build Coastguard Worker      }
80*30877f79SAndroid Build Coastguard Worker    });
81*30877f79SAndroid Build Coastguard Worker~~~
82*30877f79SAndroid Build Coastguard Worker{: .language-java}
83*30877f79SAndroid Build Coastguard Worker
84*30877f79SAndroid Build Coastguard Worker## Customizing playback ##
85*30877f79SAndroid Build Coastguard Worker
86*30877f79SAndroid Build Coastguard WorkerExoPlayer provides multiple ways for you to tailor playback experience to your
87*30877f79SAndroid Build Coastguard Workerapp's needs. See the [Customization page][] for examples.
88*30877f79SAndroid Build Coastguard Worker
89*30877f79SAndroid Build Coastguard Worker### Disabling chunkless preparation ###
90*30877f79SAndroid Build Coastguard Worker
91*30877f79SAndroid Build Coastguard WorkerBy default, ExoPlayer will use chunkless preparation. This means that ExoPlayer
92*30877f79SAndroid Build Coastguard Workerwill only use the information in the multivariant playlist to prepare the
93*30877f79SAndroid Build Coastguard Workerstream, which works if the `#EXT-X-STREAM-INF` tags contain the `CODECS`
94*30877f79SAndroid Build Coastguard Workerattribute.
95*30877f79SAndroid Build Coastguard Worker
96*30877f79SAndroid Build Coastguard WorkerYou may need to disable this feature if your media segments contain muxed
97*30877f79SAndroid Build Coastguard Workerclosed-caption tracks that are not declared in the multivariant playlist with a
98*30877f79SAndroid Build Coastguard Worker`#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS` tag. Otherwise, these closed-caption tracks
99*30877f79SAndroid Build Coastguard Workerwon't be detected and played. You can disable chunkless preparation in the
100*30877f79SAndroid Build Coastguard Worker`HlsMediaSource.Factory` as shown in the following snippet. Note that this
101*30877f79SAndroid Build Coastguard Workerwill increase start up time as ExoPlayer needs to download a media segment to
102*30877f79SAndroid Build Coastguard Workerdiscover these additional tracks and it is preferable to declare the
103*30877f79SAndroid Build Coastguard Workerclosed-caption tracks in the multivariant playlist instead.
104*30877f79SAndroid Build Coastguard Worker~~~
105*30877f79SAndroid Build Coastguard WorkerHlsMediaSource hlsMediaSource =
106*30877f79SAndroid Build Coastguard Worker    new HlsMediaSource.Factory(dataSourceFactory)
107*30877f79SAndroid Build Coastguard Worker        .setAllowChunklessPreparation(false)
108*30877f79SAndroid Build Coastguard Worker        .createMediaSource(MediaItem.fromUri(hlsUri));
109*30877f79SAndroid Build Coastguard Worker~~~
110*30877f79SAndroid Build Coastguard Worker{: .language-java}
111*30877f79SAndroid Build Coastguard Worker
112*30877f79SAndroid Build Coastguard Worker## Creating high quality HLS content ##
113*30877f79SAndroid Build Coastguard Worker
114*30877f79SAndroid Build Coastguard WorkerIn order to get the most out of ExoPlayer, there are certain guidelines you can
115*30877f79SAndroid Build Coastguard Workerfollow to improve your HLS content. Read our [Medium post about HLS playback in
116*30877f79SAndroid Build Coastguard WorkerExoPlayer][] for a full explanation. The main points are:
117*30877f79SAndroid Build Coastguard Worker
118*30877f79SAndroid Build Coastguard Worker* Use precise segment durations.
119*30877f79SAndroid Build Coastguard Worker* Use a continuous media stream; avoid changes in the media structure across
120*30877f79SAndroid Build Coastguard Worker  segments.
121*30877f79SAndroid Build Coastguard Worker* Use the `#EXT-X-INDEPENDENT-SEGMENTS` tag.
122*30877f79SAndroid Build Coastguard Worker* Prefer demuxed streams, as opposed to files that include both video and audio.
123*30877f79SAndroid Build Coastguard Worker* Include all information you can in the Multivariant Playlist.
124*30877f79SAndroid Build Coastguard Worker
125*30877f79SAndroid Build Coastguard WorkerThe following guidelines apply specifically for live streams:
126*30877f79SAndroid Build Coastguard Worker
127*30877f79SAndroid Build Coastguard Worker* Use the `#EXT-X-PROGRAM-DATE-TIME` tag.
128*30877f79SAndroid Build Coastguard Worker* Use the `#EXT-X-DISCONTINUITY-SEQUENCE` tag.
129*30877f79SAndroid Build Coastguard Worker* Provide a long live window. One minute or more is great.
130*30877f79SAndroid Build Coastguard Worker
131*30877f79SAndroid Build Coastguard Worker[HlsMediaSource]: {{ site.exo_sdk }}/source/hls/HlsMediaSource.html
132*30877f79SAndroid Build Coastguard Worker[HTTP Live Streaming]: https://tools.ietf.org/html/rfc8216
133*30877f79SAndroid Build Coastguard Worker[UI components]: {{ site.baseurl }}/ui-components.html
134*30877f79SAndroid Build Coastguard Worker[Customization page]: {{ site.baseurl }}/customization.html
135*30877f79SAndroid Build Coastguard Worker[Medium post about HLS playback in ExoPlayer]: https://medium.com/google-exoplayer/hls-playback-in-exoplayer-a33959a47be7
136