直播

ExoPlayer 可开箱即用地播放大多数自适应直播,没有任何特殊的 配置。如需了解详情,请参阅“支持的格式”页面

自适应直播提供一个窗口显示可用媒体,该窗口会在 以便与当前实时同步。也就是说 始终位于此窗口中的某个位置,在大多数情况下 实时生成视频流两者的区别在于 当前实时播放的位置和播放位置称为实时偏移

检测和监控直播

每次更新活动窗口时,注册 Player.Listener 个实例 将收到 onTimelineChanged 事件。您可以检索 通过查询各种 PlayerTimeline.Window 来实时播放当前内容 方法,如下图所示。

活动窗口

  • Player.isCurrentWindowLive 指示当前播放的媒体 项是直播。即使直播视频流 已结束。
  • Player.isCurrentWindowDynamic 指示当前播放的媒体 商品仍在更新中。这通常适用于 尚未结束。请注意,对于部分国家/地区的非直播视频流 案例
  • Player.getCurrentLiveOffset 返回当前实数之间的偏移量 播放时间及播放位置(如果有)。
  • Player.getDuration 用于返回当前活动窗口的时长。
  • Player.getCurrentPosition 返回相对于 开始时间
  • Player.getCurrentMediaItem 返回当前媒体项,其中 MediaItem.liveConfiguration 包含应用为目标提供的替换项 实时偏移和实时偏移调整参数。
  • Player.getCurrentTimeline 会返回一个以 Timeline。可以从 Timeline 中检索当前的 Timeline.Window 使用 Player.getCurrentWindowIndexTimeline.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.setLiveConfigurationMediaItem 值为基础。
  • 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 将直播偏移量调整为 播放速度会略有变化玩家将尝试根据目标 实时偏移,但也会尝试对 网络状况的变化例如,如果在播放过程中发生重新缓冲, 播放器会稍微减慢播放速度,以便离直播更远 边缘。如果网络随后变得足够稳定,可以支持在靠近 则播放器会加快播放速度, 目标实时偏移量。

如果您不希望自动调整播放速度,可以通过以下方法将其停用: 将 minPlaybackSpeedmaxPlaybackSpeed 属性设置为 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 的相关自定义参数如下:

  • fallbackMinPlaybackSpeedfallbackMaxPlaybackSpeed:最小值和 最大播放速度,可用于调整 和应用提供的 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
  }
}