直播

ExoPlayer 無須進行任何特殊設定,就能立即播放大部分自動調整式直播。詳情請參閱「支援的格式」頁面

自動調整式直播功能會以固定的間隔更新可用媒體,以便與當前的即時互動。這表示播放位置一律會在這個視窗中的某個位置,而大多數情況下,最接近產生串流的當下時間。目前即時與播放位置之間的差異稱為「即時偏移」

偵測及監控即時播放

每次更新直播時,已註冊的 Player.Listener 執行個體都會收到 onTimelineChanged 事件。您可以查詢各種 PlayerTimeline.Window 方法,擷取目前即時播放的詳細資料,如下圖所示。

使用中的視窗

  • Player.isCurrentWindowLive 表示目前播放的媒體項目是否為直播。即使直播活動已結束,這個值仍為 true。
  • Player.isCurrentWindowDynamic 表示目前播放的媒體項目是否仍在更新。如果是尚未結束的直播,通常發生這種情況。請注意,在某些情況下,這個標記也適用於非直播影片。
  • Player.getCurrentLiveOffset 會傳回目前即時與播放位置之間的偏移值 (如有)。
  • Player.getDuration 會傳回目前直播視窗的長度。
  • Player.getCurrentPosition 會傳回相對於直播視窗開始的播放位置。
  • Player.getCurrentMediaItem 會傳回目前的媒體項目,其中 MediaItem.liveConfiguration 包含應用程式針對目標即時偏移和即時偏移調整參數提供的覆寫值。
  • Player.getCurrentTimeline 會在 Timeline 中傳回目前的媒體結構。您可以使用 Player.getCurrentWindowIndexTimeline.getWindowTimeline 擷取目前的 Timeline.Window。在 Window 中:
    • Window.liveConfiguration 包含目標即時偏移和即時偏移調整參數。這些值以媒體中的資訊,以及 MediaItem.liveConfiguration 中設定的應用程式提供的覆寫值。
    • Window.windowStartTimeMs 是自執行期間開始的 Unix Epoch 紀元後開始的時間。
    • Window.getCurrentUnixTimeMs 是自目前即時 Epoch 紀元時間起算的 Unix Epoch 紀元時間。這個值可能會透過伺服器和用戶端之間的已知時鐘差異修正。
    • Window.getDefaultPositionMs 是播放器中預設開始播放內容的位置。

在直播中搜尋

您可以使用 Player.seekTo 跳轉至即時視窗中的任何位置。傳遞的搜尋位置是相對於即時視窗的開頭。舉例來說,seekTo(0) 會尋求即時視窗的開始時間。玩家會嘗試在跳轉後維持與跳轉位置相同的即時偏移值。

直播視窗也有預設位置,指的是播放內容。這個位置通常接近即時邊緣。您可以呼叫 Player.seekToDefaultPosition 來跳轉至預設位置。

直播播放使用者介面

ExoPlayer 的預設 UI 元件會顯示即時視窗的持續時間,以及其中目前播放位置。也就是說,每次更新實際時間如果您需要不同的行為 (例如顯示 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

舉例來說,如果播放器暫停或緩衝處理一段時間,播放位置可能會落後於直播視窗。在這種情況下,播放將會失敗,並透過 Player.Listener.onPlayerError 回報錯誤代碼 ERROR_CODE_BEHIND_LIVE_WINDOW 的例外狀況。應用程式程式碼可能會希望在預設位置繼續播放,藉此處理這類錯誤。試用版應用程式的 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
  }
}