自訂

ExoPlayer 程式庫的核心是 Player 介面。Player 提供傳統的高階媒體播放器功能 緩衝媒體、播放、暫停及跳轉。預設實作 ExoPlayer 為 不具任何假設 (因此對下列項目實施限制) 播放的媒體類型、儲存方式和位置,以及播放方式 轉譯完成的部分。與其直接實作媒體的載入與算繪作業 ExoPlayer 實作會將這項工作委派給插入的元件 建立播放器時,或新媒體來源傳遞給播放器時。 所有 ExoPlayer 實作項目通用的元件如下:

  • MediaSource執行個體,這些執行個體會定義要播放的媒體、載入媒體及 可讀取已載入媒體的來源已建立 MediaSource 執行個體 由播放器內部 MediaSource.Factory 所選擇的 MediaItem。其他 使用媒體來源播放清單 API 直接傳遞給播放器。
  • 可將 MediaItem 轉換為 MediaSourceMediaSource.Factory 執行個體。 MediaSource.Factory 會在建立播放器時插入。
  • 算繪媒體個別元件的 Renderer 執行個體。這些 會在建立播放器時插入。
  • TrackSelector,可選取 MediaSource 提供的曲目 各可用 Renderer 耗用的資源。已插入 TrackSelector 建立播放器時。
  • 控制 MediaSource 緩衝更多媒體時間的 LoadControl;以及 有多少媒體進行緩衝處理系統會插入 LoadControl 已建立。
  • 控制直播期間播放速度的 LivePlaybackSpeedControl 讓播放器靠近已設定的即時偏移量。A 罩杯 LivePlaybackSpeedControl 會在建立播放器時插入。

插入實作播放器元件的概念 都會直接套用這些功能預設實作 某些元件會將工作委派給進一步插入的元件。這樣一來 可以使用 可讓您以自訂方式設定容器

播放器自訂功能

以下列舉幾個透過插入元件自訂播放器的常見範例: 。

設定網路堆疊

歡迎參閱這個頁面,瞭解如何自訂 ExoPlayer 使用的網路堆疊。

快取從網路載入的資料

請參閱下列指南: 即時快取下載媒體

自訂伺服器互動

部分應用程式可能會想攔截 HTTP 要求和回應。建議您 插入自訂要求標頭、讀取伺服器的回應標頭、修改 要求URI 等。舉例來說,您的應用程式可以透過插入 做為請求媒體區隔的標頭格式。

以下範例說明如何透過 將自訂 DataSource.Factory 插入 DefaultMediaSourceFactory

Kotlin

val dataSourceFactory =
  DataSource.Factory {
    val dataSource = httpDataSourceFactory.createDataSource()
    // Set a custom authentication request header.
    dataSource.setRequestProperty("Header", "Value")
    dataSource
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

DataSource.Factory dataSourceFactory =
    () -> {
      HttpDataSource dataSource = httpDataSourceFactory.createDataSource();
      // Set a custom authentication request header.
      dataSource.setRequestProperty("Header", "Value");
      return dataSource;
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

在上方的程式碼片段中,插入的 HttpDataSource 包含標頭 每個 HTTP 要求中的 "Header: Value"。這個行為已在各個管道中修正 與 HTTP 來源互動

如需更詳細的方式,您可以使用 ResolvingDataSource。下列程式碼片段說明如何插入 要求標頭,接著才與 HTTP 來源互動:

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time request headers.
    dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri))
  }

Java

    DataSource.Factory dataSourceFactory =
        new ResolvingDataSource.Factory(
            httpDataSourceFactory,
            // Provide just-in-time request headers.
            dataSpec -> dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)));

您也可以使用 ResolvingDataSource 來執行 及時修改 URI,如以下程式碼片段所示:

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time URI resolution logic.
    dataSpec.withUri(resolveUri(dataSpec.uri))
  }

Java

DataSource.Factory dataSourceFactory =
    new ResolvingDataSource.Factory(
        httpDataSourceFactory,
        // Provide just-in-time URI resolution logic.
        dataSpec -> dataSpec.withUri(resolveUri(dataSpec.uri)));

自訂錯誤處理機制

實作自訂 LoadErrorHandlingPolicy 可讓應用程式自訂 ExoPlayer 對載入錯誤的回應方式舉例來說,應用程式可能需要快速失敗 而非多次重試,或者您可以自訂輪詢邏輯 控制玩家每次重試的等待時間長度。下列程式碼片段 顯示如何實作自訂輪詢邏輯:

Kotlin

val loadErrorHandlingPolicy: LoadErrorHandlingPolicy =
  object : DefaultLoadErrorHandlingPolicy() {
    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
      // Implement custom back-off logic here.
      return 0
    }
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    )
    .build()

Java

LoadErrorHandlingPolicy loadErrorHandlingPolicy =
    new DefaultLoadErrorHandlingPolicy() {
      @Override
      public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
        // Implement custom back-off logic here.
        return 0;
      }
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy))
        .build();

LoadErrorInfo 引數會包含關於載入失敗的詳細資訊, 並根據錯誤類型或失敗的要求自訂邏輯。

自訂擷取器旗標

擷取器標記可用來自訂個別格式的擷取方式 來自漸進式媒體這些配置可以在DefaultExtractorsFactory 提供給 DefaultMediaSourceFactory。以下範例傳送標記 ,此功能可讓系統根據索引尋找 MP3 串流。

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING)
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory))
    .build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING);

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

啟用固定位元率跳轉功能

針對 MP3、ADTS 和 AMR 串流,你可以啟用「近似跳轉」 使用 FLAG_ENABLE_CONSTANT_BITRATE_SEEKING 旗標的固定位元率。 您可以使用個別擷取器 DefaultExtractorsFactory.setXyzExtractorFlags 方法。目的地: 允許在支援特定擷取器的所有擷取器上 DefaultExtractorsFactory.setConstantBitrateSeekingEnabled

Kotlin

val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);

接著,您就能透過 DefaultMediaSourceFactory 插入 ExtractorsFactory,做為 。

啟用非同步緩衝區佇列

非同步緩衝區佇列是 ExoPlayer 在算繪情況下的強化項目 管道,以非同步模式運作 MediaCodec 執行個體,且 會使用其他執行緒來安排解碼及算繪資料。啟用中 以減少影格遺失和音訊截斷情形

執行 Android 12 的裝置預設會啟用非同步緩衝區佇列 (API 級別 31) 以上版本,從 Android 6.0 (API 級別 23) 開始可以手動啟用。 建議你為發現裝置掉落的特定裝置啟用這項功能 影格或音訊不足,尤其是播放受到 DRM 保護或影格速率過高時 內容。

在最簡單的情況下,您需要將 DefaultRenderersFactory 插入 方法如下:

Kotlin

val renderersFactory = 
  DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing()
val exoPlayer = ExoPlayer.Builder(context, renderersFactory).build()

Java

DefaultRenderersFactory renderersFactory =
    new DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing();
ExoPlayer exoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();

若您直接對轉譯器執行個體化,請傳遞 AsynchronousMediaCodecAdapter.FactoryMediaCodecVideoRendererMediaCodecAudioRenderer 建構函式建立而成。

使用 ForwardingPlayer 攔截方法呼叫

您可以將 Player 例項納入,以自訂其部分行為 ForwardingPlayer 的子類別和覆寫方法,以便執行 包括:

  • 請先存取參數,再傳送至委派的 Player
  • 請先從委派的 Player 存取傳回值,再傳回值。
  • 徹底重新實作該方法。

覆寫 ForwardingPlayer 方法時,請務必確認 實作項目仍遵循 Player 的自我一致性 尤其在處理預計產生 採取完全相同或相關的行為例如:

  • 如果想要覆寫每次「播放」您需要覆寫 ForwardingPlayer.playForwardingPlayer.setPlayWhenReady,因為 呼叫端預期這些方法的行為 playWhenReady = true
  • 如要變更跳轉遞增量,您必須同時覆寫 ForwardingPlayer.seekForward,即可運用自訂內容跳轉 遞增,ForwardingPlayer.getSeekForwardIncrement以便回報 正確的自訂遞增給呼叫端。
  • 如要控管玩家要宣傳的Player.Commands 執行個體,您必須同時覆寫 Player.getAvailableCommands()Player.isCommandAvailable(),以及聆聽 Player.Listener.onAvailableCommandsChanged() 回呼以便接收 來自基礎播放器的變更

MediaSource 自訂

以上範例插入了自訂元件,以便在 傳遞至播放器的 MediaItem 物件。精細自訂的部分 您也能將自訂元件插入 MediaSource 例項,可以直接傳遞至播放器。範例 以下說明如何自訂 ProgressiveMediaSource,以便使用自訂 DataSource.FactoryExtractorsFactoryLoadErrorHandlingPolicy

Kotlin

val mediaSource =
  ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
    .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
    .createMediaSource(MediaItem.fromUri(streamUri))

Java

ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
        .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
        .createMediaSource(MediaItem.fromUri(streamUri));

建立自訂元件

程式庫提供頂端所列元件的預設實作方式 請參考本頁說明,瞭解一般用途。ExoPlayer 可以使用這些元件,但 如果非標準行為, 這通常代表交易 不會十分要求關聯語意自訂導入作業的用途如下:

  • Renderer:建議您實作自訂 Renderer 來處理 媒體型別所支援的媒體類型, 資源庫。
  • TrackSelector:實作自訂 TrackSelector 可讓應用程式執行 開發人員變更 MediaSource 公開測試群組的方式 並選取要用於每個可用 Renderer 的用量。
  • LoadControl:實作自訂 LoadControl 可讓應用程式執行 開發人員更改玩家的緩衝處理政策。
  • Extractor:如果您目前需要支援某個容器格式 該程式庫支援,建議您實作自訂的 Extractor 類別。
  • MediaSource – 實作自訂 MediaSource 類別可 如果您想要取得媒體樣本並提供給轉譯器中的轉譯器使用 自訂方式,或想導入自訂 MediaSource 合成選項 行為
  • MediaSource.Factory – 導入自訂 MediaSource.Factory 可讓應用程式自訂 MediaSource 的建立方式 來自 MediaItem
  • DataSource:ExoPlayer 的上游套件已包含多種 針對不同用途實作 DataSource。建議您 實作自己的 DataSource 類別,透過其他方式載入資料,例如 使用自訂通訊協定、自訂 HTTP 堆疊,或從自訂永久磁碟 快取。

建立自訂元件時,建議您採取下列做法:

  • 如果自訂元件需要將事件回報給應用程式,建議您 您使用與現有 ExoPlayer 元件相同的模型 使用 EventDispatcher 類別,或與程式碼一起傳遞 Handler 的範例 元件的建構函式。
  • 建議自訂元件使用與現有 ExoPlayer 相同的模型 元件,允許應用程式在播放期間重新設定。方法如下 自訂元件應導入 PlayerMessage.Target,並接收 變更 handleMessage 方法的設定變更應用程式程式碼應 呼叫 ExoPlayer 的 createMessage 方法以傳遞設定變更。 設定訊息,並使用 PlayerMessage.send。傳送要在播放執行緒上傳送的訊息 確保這些執行作業與 遊戲製作的影片