ExoPlayer 可开箱即用地播放大多数自适应直播,没有任何特殊的 配置。如需了解详情,请参阅“支持的格式”页面。
自适应直播提供一个窗口显示可用媒体,该窗口会在 以便与当前实时同步。也就是说 始终位于此窗口中的某个位置,在大多数情况下 实时生成视频流两者的区别在于 当前实时播放的位置和播放位置称为实时偏移。
检测和监控直播
每次更新活动窗口时,注册 Player.Listener
个实例
将收到 onTimelineChanged
事件。您可以检索
通过查询各种 Player
和 Timeline.Window
来实时播放当前内容
方法,如下图所示。
Player.isCurrentWindowLive
指示当前播放的媒体 项是直播。即使直播视频流 已结束。Player.isCurrentWindowDynamic
指示当前播放的媒体 商品仍在更新中。这通常适用于 尚未结束。请注意,对于部分国家/地区的非直播视频流 案例Player.getCurrentLiveOffset
返回当前实数之间的偏移量 播放时间及播放位置(如果有)。Player.getDuration
用于返回当前活动窗口的时长。Player.getCurrentPosition
返回相对于 开始时间Player.getCurrentMediaItem
返回当前媒体项,其中MediaItem.liveConfiguration
包含应用为目标提供的替换项 实时偏移和实时偏移调整参数。Player.getCurrentTimeline
会返回一个以Timeline
。可以从Timeline
中检索当前的Timeline.Window
使用Player.getCurrentWindowIndex
和Timeline.getWindow
。在Window
: <ph type="x-smartling-placeholder">- </ph>
Window.liveConfiguration
包含目标实时偏移量和实时偏移量 调整参数。这些值基于媒体中的信息 以及MediaItem.liveConfiguration
中设置的任何应用提供的替换项。Window.windowStartTimeMs
是自 Unix Epoch 起的时间, 。Window.getCurrentUnixTimeMs
是自 实时更新。此值可以通过已知的时钟差异校正 和客户端之间的通信Window.getDefaultPositionMs
是实时窗口中的 播放器会默认开始播放
在直播中查找
您可以使用 Player.seekTo
跳转至实时窗口内的任意位置。寻找
相对于实时窗口的起始位置。例如:
seekTo(0)
会跳转到实时窗口的起始位置。播放器会尝试
保持与跳转后跳转位置相同的活动偏移量。
实时窗口还有一个默认位置
start 的值。此位置通常靠近实际边缘。您可以跳转
通过调用 Player.seekToDefaultPosition
调整到默认位置。
实时播放界面
ExoPlayer 的默认界面组件显示活动窗口的时长,以及
当前播放位置也就是说,该位置
向后跳转。如果您需要使用
行为(例如显示 Unix 时间或当前实时偏移量),您可以
请创建 PlayerControlView
分支并对其进行修改,以满足您的需求。
配置直播参数
ExoPlayer 使用一些参数来控制播放位置的偏移量 以及可用于选择实时同步的 调整此偏移量
ExoPlayer 从三个位置获取这些参数的值,以降序排列 优先级顺序(使用找到的第一个值):
- 以传递给
MediaItem.Builder.setLiveConfiguration
的MediaItem
值为基础。 - 在
DefaultMediaSourceFactory
上设置的全局默认值。 - 直接从媒体读取值。
Kotlin
// Global settings. val player = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build() // Per MediaItem settings. val mediaItem = MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build() ) .build() player.setMediaItem(mediaItem)
Java
// Global settings. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build(); // Per MediaItem settings. MediaItem mediaItem = new MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()) .build(); player.setMediaItem(mediaItem);
可用的配置值包括:
targetOffsetMs
:目标实时偏移量。玩家会尝试 (如果可能的话)。minOffsetMs
:允许的最小实时偏移量。即使调整 当前网络状况的偏差,则播放器不会试图低于 该偏移量。maxOffsetMs
:允许的实时偏移上限。即使调整 当前网络状况的偏差,则播放器不会试图超过 该偏移量。minPlaybackSpeed
:播放器可用于回退的最小播放速度 (即尝试达到目标实时偏移量时)maxPlaybackSpeed
:播放器可用于跟上进度的最大播放速度 (即尝试达到目标实时偏移量时)
播放速度调整
播放低延迟直播时,ExoPlayer 将直播偏移量调整为 播放速度会略有变化玩家将尝试根据目标 实时偏移,但也会尝试对 网络状况的变化例如,如果在播放过程中发生重新缓冲, 播放器会稍微减慢播放速度,以便离直播更远 边缘。如果网络随后变得足够稳定,可以支持在靠近 则播放器会加快播放速度, 目标实时偏移量。
如果您不希望自动调整播放速度,可以通过以下方法将其停用:
将 minPlaybackSpeed
和 maxPlaybackSpeed
属性设置为 1.0f
。
同样,您也可以将
明确设置为 1.0f
以外的值。请参阅
请参阅上面的“配置”部分
有关如何设置这些属性的详情。
自定义播放速度调整算法
如果启用了速度调整,LivePlaybackSpeedControl
会定义
进行调整。也可以将自定义
LivePlaybackSpeedControl
,也可以自定义默认实现,即
DefaultLivePlaybackSpeedControl
。在这两种情况下
构建播放器:
Kotlin
val player = ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build() ) .build()
Java
ExoPlayer player = new ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( new DefaultLivePlaybackSpeedControl.Builder() .setFallbackMaxPlaybackSpeed(1.04f) .build()) .build();
DefaultLivePlaybackSpeedControl
的相关自定义参数如下:
fallbackMinPlaybackSpeed
和fallbackMaxPlaybackSpeed
:最小值和 最大播放速度,可用于调整 和应用提供的MediaItem
也都定义了限制。proportionalControlFactor
:控制速度调整的平滑程度。答 较高的值会使相应调整变得更加突然和被动,但也更有可能 声音。值越小,不同速度之间的转换越顺畅, 但代价是速度变慢targetLiveOffsetIncrementOnRebufferMs
:此值会添加到目标中 实时偏移,以便更加谨慎地处理。 将值设置为 0 即可停用此功能。minPossibleLiveOffsetSmoothingFactor
:指数平滑因数, 用于根据当前的 缓冲的媒体。如果值非常接近于 1,则表示估算值更高 并且可能需要更长的时间来适应改善的网络条件,而 值越小,估算值的调整速度就越快, 重新缓冲。
BehindLiveWindowException 和 ERROR_CODE_BEHIND_LIVE_WINDOW
播放位置可能会落后于直播窗口之后,例如,如果播放器
暂停或缓冲的时间足够长。如果发生这种情况
播放失败,并显示错误代码的异常
ERROR_CODE_BEHIND_LIVE_WINDOW
将通过以下方式报告:
Player.Listener.onPlayerError
。应用代码可能希望处理
从默认位置恢复播放,从而避免发生错误。PlayerActivity
演示版应用对这种方法进行了演示。
Kotlin
override fun onPlayerError(error: PlaybackException) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition() player.prepare() } else { // Handle other errors } }
Java
@Override public void onPlayerError(PlaybackException error) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition(); player.prepare(); } else { // Handle other errors } }