1*30877f79SAndroid Build Coastguard Worker--- 2*30877f79SAndroid Build Coastguard Workertitle: Live streaming 3*30877f79SAndroid Build Coastguard Worker--- 4*30877f79SAndroid Build Coastguard Worker 5*30877f79SAndroid Build Coastguard WorkerExoPlayer plays most adaptive live streams out-of-the-box without any special 6*30877f79SAndroid Build Coastguard Workerconfiguration. See the [Supported Formats page][] for more details. 7*30877f79SAndroid Build Coastguard Worker 8*30877f79SAndroid Build Coastguard WorkerAdaptive live streams offer a window of available media that is updated in 9*30877f79SAndroid Build Coastguard Workerregular intervals to move with the current real-time. That means the playback 10*30877f79SAndroid Build Coastguard Workerposition will always be somewhere in this window, in most cases close to the 11*30877f79SAndroid Build Coastguard Workercurrent real-time at which the stream is being produced. The difference between 12*30877f79SAndroid Build Coastguard Workerthe current real-time and the playback position is called the *live offset*. 13*30877f79SAndroid Build Coastguard Worker 14*30877f79SAndroid Build Coastguard WorkerUnlike adaptive live streams, progressive live streams do not have a live window 15*30877f79SAndroid Build Coastguard Workerand can only be played at one position. The documentation on this page is only 16*30877f79SAndroid Build Coastguard Workerrelevant to adaptive live streams. 17*30877f79SAndroid Build Coastguard Worker{:.info} 18*30877f79SAndroid Build Coastguard Worker 19*30877f79SAndroid Build Coastguard WorkerExoPlayer adjusts the live offset by slightly changing the playback speed. 20*30877f79SAndroid Build Coastguard WorkerThe player will try to match user and media preferences, but will also try to 21*30877f79SAndroid Build Coastguard Workerreact to changing network conditions. For example, if rebuffers occur during 22*30877f79SAndroid Build Coastguard Workerplayback, the player will move further away from the live edge. If there is 23*30877f79SAndroid Build Coastguard Workerenough available buffer over a longer period of time, the player will move 24*30877f79SAndroid Build Coastguard Workercloser to the live edge again. 25*30877f79SAndroid Build Coastguard Worker 26*30877f79SAndroid Build Coastguard Worker## Detecting and monitoring live playbacks ## 27*30877f79SAndroid Build Coastguard Worker 28*30877f79SAndroid Build Coastguard WorkerEvery time a live window is updated, registered `Player.Listener` instances 29*30877f79SAndroid Build Coastguard Workerwill receive an `onTimelineChanged` event. You can retrieve details about the 30*30877f79SAndroid Build Coastguard Workercurrent live playback by querying various `Player` and `Timeline.Window` 31*30877f79SAndroid Build Coastguard Workermethods, as listed below and shown in the following figure. 32*30877f79SAndroid Build Coastguard Worker 33*30877f79SAndroid Build Coastguard Worker{% include figure.html url="/images/live-window.png" index="1" caption="Live window" %} 34*30877f79SAndroid Build Coastguard Worker 35*30877f79SAndroid Build Coastguard Worker* `Player.isCurrentWindowLive` indicates whether the currently playing media 36*30877f79SAndroid Build Coastguard Worker item is a live stream. This value is still true even if the live stream has 37*30877f79SAndroid Build Coastguard Worker ended. 38*30877f79SAndroid Build Coastguard Worker* `Player.isCurrentWindowDynamic` indicates whether the currently playing media 39*30877f79SAndroid Build Coastguard Worker item is still being updated. This is usually true for live streams that are 40*30877f79SAndroid Build Coastguard Worker not yet ended. Note that this flag is also true for non-live streams in some 41*30877f79SAndroid Build Coastguard Worker cases. 42*30877f79SAndroid Build Coastguard Worker* `Player.getCurrentLiveOffset` returns the offset between the current real 43*30877f79SAndroid Build Coastguard Worker time and the playback position (if available). 44*30877f79SAndroid Build Coastguard Worker* `Player.getDuration` returns the length of the current live window. 45*30877f79SAndroid Build Coastguard Worker* `Player.getCurrentPosition` returns the playback position relative to the 46*30877f79SAndroid Build Coastguard Worker start of the live window. 47*30877f79SAndroid Build Coastguard Worker* `Player.getCurrentMediaItem` returns the current media item, where 48*30877f79SAndroid Build Coastguard Worker `MediaItem.liveConfiguration` contains app-provided overrides for the target 49*30877f79SAndroid Build Coastguard Worker live offset and live offset adjustment parameters. 50*30877f79SAndroid Build Coastguard Worker* `Player.getCurrentTimeline` returns the current media structure in a 51*30877f79SAndroid Build Coastguard Worker `Timeline`. The current `Timeline.Window` can be retrieved from the `Timeline` 52*30877f79SAndroid Build Coastguard Worker using `Player.getCurrentWindowIndex` and `Timeline.getWindow`. Within the 53*30877f79SAndroid Build Coastguard Worker `Window`: 54*30877f79SAndroid Build Coastguard Worker * `Window.liveConfiguration` contains the target live offset and live offset 55*30877f79SAndroid Build Coastguard Worker adjustment parameters. These values are based on information in the media 56*30877f79SAndroid Build Coastguard Worker and any app-provided overrides set in `MediaItem.liveConfiguration`. 57*30877f79SAndroid Build Coastguard Worker * `Window.windowStartTimeMs` is the time since the Unix Epoch at which the 58*30877f79SAndroid Build Coastguard Worker live window starts. 59*30877f79SAndroid Build Coastguard Worker * `Window.getCurrentUnixTimeMs` is the time since the Unix Epoch of the 60*30877f79SAndroid Build Coastguard Worker current real-time. This value may be corrected by a known clock difference 61*30877f79SAndroid Build Coastguard Worker between the server and the client. 62*30877f79SAndroid Build Coastguard Worker * `Window.getDefaultPositionMs` is the position in the live window at which 63*30877f79SAndroid Build Coastguard Worker the player will start playback by default. 64*30877f79SAndroid Build Coastguard Worker 65*30877f79SAndroid Build Coastguard Worker## Seeking in live streams ## 66*30877f79SAndroid Build Coastguard Worker 67*30877f79SAndroid Build Coastguard WorkerYou can seek to anywhere within the live window using `Player.seekTo`. The seek 68*30877f79SAndroid Build Coastguard Workerposition passed is relative to the start of the live window. For example, 69*30877f79SAndroid Build Coastguard Worker `seekTo(0)` will seek to the start of the live window. The player will try to 70*30877f79SAndroid Build Coastguard Workerkeep the same live offset as the seeked-to position after a seek. 71*30877f79SAndroid Build Coastguard Worker 72*30877f79SAndroid Build Coastguard WorkerThe live window also has a default position at which playback is supposed to 73*30877f79SAndroid Build Coastguard Workerstart. This position is usually somewhere close to the live edge. You can seek 74*30877f79SAndroid Build Coastguard Workerto the default position by calling `Player.seekToDefaultPosition`. 75*30877f79SAndroid Build Coastguard Worker 76*30877f79SAndroid Build Coastguard Worker## Live playback UI ## 77*30877f79SAndroid Build Coastguard Worker 78*30877f79SAndroid Build Coastguard WorkerExoPlayer's [default UI components][] show the duration of the live window and 79*30877f79SAndroid Build Coastguard Workerthe current playback position within it. This means the position will appear to 80*30877f79SAndroid Build Coastguard Workerjump backwards each time the live window is updated. If you need different 81*30877f79SAndroid Build Coastguard Workerbehavior, for example showing the Unix time or the current live offset, you can 82*30877f79SAndroid Build Coastguard Workerfork `StyledPlayerControlView` and modify it to suit your needs. 83*30877f79SAndroid Build Coastguard Worker 84*30877f79SAndroid Build Coastguard WorkerThere is a [pending feature request (#2213)][] for ExoPlayer's default UI 85*30877f79SAndroid Build Coastguard Workercomponents to support additional modes when playing live streams. 86*30877f79SAndroid Build Coastguard Worker{:.info} 87*30877f79SAndroid Build Coastguard Worker 88*30877f79SAndroid Build Coastguard Worker## Configuring live playback parameters ## 89*30877f79SAndroid Build Coastguard Worker 90*30877f79SAndroid Build Coastguard WorkerBy default, ExoPlayer uses live playback parameters defined by the media. If you 91*30877f79SAndroid Build Coastguard Workerwant to configure the live playback parameters yourself, you can set them on a 92*30877f79SAndroid Build Coastguard Workerper `MediaItem` basis by calling `MediaItem.Builder.setLiveConfiguration`. If 93*30877f79SAndroid Build Coastguard Workeryou'd like to set these values globally for all items, you can set them on the 94*30877f79SAndroid Build Coastguard Worker`DefaultMediaSourceFactory` provided to the player. In both cases, the provided 95*30877f79SAndroid Build Coastguard Workervalues will override parameters defined by the media. 96*30877f79SAndroid Build Coastguard Worker 97*30877f79SAndroid Build Coastguard Worker~~~ 98*30877f79SAndroid Build Coastguard Worker// Global settings. 99*30877f79SAndroid Build Coastguard WorkerExoPlayer player = 100*30877f79SAndroid Build Coastguard Worker new ExoPlayer.Builder(context) 101*30877f79SAndroid Build Coastguard Worker .setMediaSourceFactory( 102*30877f79SAndroid Build Coastguard Worker new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) 103*30877f79SAndroid Build Coastguard Worker .build(); 104*30877f79SAndroid Build Coastguard Worker 105*30877f79SAndroid Build Coastguard Worker// Per MediaItem settings. 106*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = 107*30877f79SAndroid Build Coastguard Worker new MediaItem.Builder() 108*30877f79SAndroid Build Coastguard Worker .setUri(mediaUri) 109*30877f79SAndroid Build Coastguard Worker .setLiveConfiguration( 110*30877f79SAndroid Build Coastguard Worker new MediaItem.LiveConfiguration.Builder() 111*30877f79SAndroid Build Coastguard Worker .setMaxPlaybackSpeed(1.02f) 112*30877f79SAndroid Build Coastguard Worker .build()) 113*30877f79SAndroid Build Coastguard Worker .build(); 114*30877f79SAndroid Build Coastguard Workerplayer.setMediaItem(mediaItem); 115*30877f79SAndroid Build Coastguard Worker~~~ 116*30877f79SAndroid Build Coastguard Worker{: .language-java} 117*30877f79SAndroid Build Coastguard Worker 118*30877f79SAndroid Build Coastguard WorkerAvailable configuration values are: 119*30877f79SAndroid Build Coastguard Worker 120*30877f79SAndroid Build Coastguard Worker* `targetOffsetMs`: The target live offset. The player will attempt to get 121*30877f79SAndroid Build Coastguard Worker close to this live offset during playback if possible. 122*30877f79SAndroid Build Coastguard Worker* `minOffsetMs`: The minimum allowed live offset. Even when adjusting the 123*30877f79SAndroid Build Coastguard Worker offset to current network conditions, the player will not attempt to get below 124*30877f79SAndroid Build Coastguard Worker this offset during playback. 125*30877f79SAndroid Build Coastguard Worker* `maxOffsetMs`: The maximum allowed live offset. Even when adjusting the 126*30877f79SAndroid Build Coastguard Worker offset to current network conditions, the player will not attempt to get above 127*30877f79SAndroid Build Coastguard Worker this offset during playback. 128*30877f79SAndroid Build Coastguard Worker* `minPlaybackSpeed`: The minimum playback speed the player can use to fall back 129*30877f79SAndroid Build Coastguard Worker when trying to reach the target live offset. 130*30877f79SAndroid Build Coastguard Worker* `maxPlaybackSpeed`: The maximum playback speed the player can use to catch up 131*30877f79SAndroid Build Coastguard Worker when trying to reach the target live offset. 132*30877f79SAndroid Build Coastguard Worker 133*30877f79SAndroid Build Coastguard WorkerIf automatic playback speed adjustment is not desired, it can be disabled by 134*30877f79SAndroid Build Coastguard Workersetting `minPlaybackSpeed` and `maxPlaybackSpeed` to `1.0f`. 135*30877f79SAndroid Build Coastguard Worker 136*30877f79SAndroid Build Coastguard Worker## BehindLiveWindowException and ERROR_CODE_BEHIND_LIVE_WINDOW ## 137*30877f79SAndroid Build Coastguard Worker 138*30877f79SAndroid Build Coastguard WorkerThe playback position may fall behind the live window, for example if the player 139*30877f79SAndroid Build Coastguard Workeris paused or buffering for a long enough period of time. If this happens then 140*30877f79SAndroid Build Coastguard Workerplayback will fail and an exception with error code 141*30877f79SAndroid Build Coastguard Worker`ERROR_CODE_BEHIND_LIVE_WINDOW` will be reported via 142*30877f79SAndroid Build Coastguard Worker`Player.Listener.onPlayerError`. Application code may wish to handle such 143*30877f79SAndroid Build Coastguard Workererrors by resuming playback at the default position. The [PlayerActivity][] of 144*30877f79SAndroid Build Coastguard Workerthe demo app exemplifies this approach. 145*30877f79SAndroid Build Coastguard Worker 146*30877f79SAndroid Build Coastguard Worker~~~ 147*30877f79SAndroid Build Coastguard Worker@Override 148*30877f79SAndroid Build Coastguard Workerpublic void onPlayerError(PlaybackException error) { 149*30877f79SAndroid Build Coastguard Worker if (eror.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { 150*30877f79SAndroid Build Coastguard Worker // Re-initialize player at the current live window default position. 151*30877f79SAndroid Build Coastguard Worker player.seekToDefaultPosition(); 152*30877f79SAndroid Build Coastguard Worker player.prepare(); 153*30877f79SAndroid Build Coastguard Worker } else { 154*30877f79SAndroid Build Coastguard Worker // Handle other errors. 155*30877f79SAndroid Build Coastguard Worker } 156*30877f79SAndroid Build Coastguard Worker} 157*30877f79SAndroid Build Coastguard Worker~~~ 158*30877f79SAndroid Build Coastguard Worker{: .language-java} 159*30877f79SAndroid Build Coastguard Worker 160*30877f79SAndroid Build Coastguard Worker## Customizing the playback speed adjustment algorithm ## 161*30877f79SAndroid Build Coastguard Worker 162*30877f79SAndroid Build Coastguard WorkerTo stay close to the target live offset, a `LivePlaybackSpeedControl` is used to 163*30877f79SAndroid Build Coastguard Workermake adjustments to the playback speed during live playbacks. It's possible to 164*30877f79SAndroid Build Coastguard Workerimplement a custom `LivePlaybackSpeedControl`, or to customize the default 165*30877f79SAndroid Build Coastguard Workerimplementation, which is `DefaultLivePlaybackSpeedControl`. In both cases an 166*30877f79SAndroid Build Coastguard Workerinstance can be set when building the player: 167*30877f79SAndroid Build Coastguard Worker 168*30877f79SAndroid Build Coastguard Worker~~~ 169*30877f79SAndroid Build Coastguard WorkerExoPlayer player = 170*30877f79SAndroid Build Coastguard Worker new ExoPlayer.Builder(context) 171*30877f79SAndroid Build Coastguard Worker .setLivePlaybackSpeedControl( 172*30877f79SAndroid Build Coastguard Worker new DefaultLivePlaybackSpeedControl.Builder() 173*30877f79SAndroid Build Coastguard Worker .setFallbackMaxPlaybackSpeed(1.04f) 174*30877f79SAndroid Build Coastguard Worker .build()) 175*30877f79SAndroid Build Coastguard Worker .build(); 176*30877f79SAndroid Build Coastguard Worker~~~ 177*30877f79SAndroid Build Coastguard Worker{: .language-java} 178*30877f79SAndroid Build Coastguard Worker 179*30877f79SAndroid Build Coastguard WorkerRelevant customization parameters of `DefaultLivePlaybackSpeedControl` are: 180*30877f79SAndroid Build Coastguard Worker 181*30877f79SAndroid Build Coastguard Worker* `fallbackMinPlaybackSpeed` and `fallbackMaxPlaybackSpeed`: The minimum and 182*30877f79SAndroid Build Coastguard Worker maximum playback speeds that can be used for adjustment if neither the media 183*30877f79SAndroid Build Coastguard Worker nor the app-provided `MediaItem` define limits. 184*30877f79SAndroid Build Coastguard Worker* `proportionalControlFactor`: Controls how smooth the speed adjustment is. A 185*30877f79SAndroid Build Coastguard Worker high value makes adjustments more sudden and reactive, but also more likely to 186*30877f79SAndroid Build Coastguard Worker be audible. A smaller value results in a smoother transition between speeds, 187*30877f79SAndroid Build Coastguard Worker at the cost of being slower. 188*30877f79SAndroid Build Coastguard Worker* `targetLiveOffsetIncrementOnRebufferMs`: This value is added to the target 189*30877f79SAndroid Build Coastguard Worker live offset whenever a rebuffer occurs, in order to proceed more cautiously. 190*30877f79SAndroid Build Coastguard Worker This feature can be disabled by setting the value to 0. 191*30877f79SAndroid Build Coastguard Worker* `minPossibleLiveOffsetSmoothingFactor`: An exponential smoothing factor that 192*30877f79SAndroid Build Coastguard Worker is used to track the minimum possible live offset based on the currently 193*30877f79SAndroid Build Coastguard Worker buffered media. A value very close to 1 means that the estimation is more 194*30877f79SAndroid Build Coastguard Worker cautious and may take longer to adjust to improved network conditions, whereas 195*30877f79SAndroid Build Coastguard Worker a lower value means the estimation will adjust faster at a higher risk of 196*30877f79SAndroid Build Coastguard Worker running into rebuffers. 197*30877f79SAndroid Build Coastguard Worker 198*30877f79SAndroid Build Coastguard Worker[Supported Formats page]: {{ site.baseurl }}/supported-formats.html 199*30877f79SAndroid Build Coastguard Worker[default UI components]: {{ site.baseurl }}/ui-components.html 200*30877f79SAndroid Build Coastguard Worker[pending feature request (#2213)]: https://github.com/google/ExoPlayer/issues/2213 201*30877f79SAndroid Build Coastguard Worker[PlayerActivity]: {{ site.release_v2 }}/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java 202