疑難排解


修正「不允許明文 HTTP 流量」錯誤數

如果應用程式要求明文 HTTP 流量 (也就是 http://,而非 https://)。 或是不允許使用。如果應用程式指定的是 Android 9 (API 級別 28) 以上版本,請採用明文 HTTP 流量預設為停用。

如果您的應用程式需要處理明文 HTTP 流量,您就必須使用 允許該網路的安全性設定。查看 Android 網路安全說明文件 。如要啟用所有明文 HTTP 流量 將 android:usesCleartextTraffic="true" 到應用程式的 application 元素 AndroidManifest.xml

ExoPlayer 試用版應用程式會使用預設的網路安全性設定,因此 不允許明文 HTTP 流量如要啟用,請按照 。

修正「SSLHandshakeException」,「CertPathValidatorException」和「ERR_CERT_AUTHORITY_INVALID」錯誤數

SSLHandshakeExceptionCertPathValidatorExceptionERR_CERT_AUTHORITY_INVALID 都代表伺服器的安全資料傳輸層 (SSL) 有問題 憑證這些錯誤並非特定 ExoPlayer。詳情請見 Android 的 SSL 說明文件 ,掌握更多詳細資訊。

為什麼無法搜尋某些媒體檔案?

根據預設,ExoPlayer 不支援在媒體上尋找唯一的方法 執行準確的跳轉作業是讓播放器能 整個檔案。ExoPlayer 將這類檔案視為無法瀏覽。大多數新式媒體 容器格式包含用來查詢的中繼資料 (例如範例索引), 定義明確的跳轉演算法 (例如,內插式雙欄搜尋「Ogg」搜尋);或 表示內容為固定位元率。高效率的跳轉作業 並由 ExoPlayer 提供支援

如果您需要用跳轉功能但無法瀏覽的媒體內容,建議您將 使用更合適的容器格式如果是 MP3、ADTS 和 AMR 檔案, 您亦可以啟用跳轉功能 (假設這些檔案具有常數 如上所述 請按這裡

為什麼在某些 MP3 檔案中搜尋不準確?

可變動位元率 (VBR) MP3 檔案基本上不適合用於 則需要精準跳轉。原因有兩種:

  1. 至於確切跳轉,容器格式最好能 標頭中的時間與位元組對應。這個對應可以讓玩家 要求的搜尋時間到對應的位元組偏移,然後開始要求 剖析及播放該位移中的媒體可供存取的標頭 然而,在 MP3 中指定此對應 (如 XING 標頭) 通常是很遺憾, 不精確
  2. 針對無法提供精確時間對應位元組的容器格式 (或 任何時間對位元組的對應) 仍可執行 ,於 如此一來,玩家就能將搜尋時間對應到 位元組偏移, 開始從偏移量要求媒體, 剖析第一個 的絕對樣本時間戳記,以及有效執行引導式二進位檔搜尋 直到找出正確的樣本很遺憾 MP3 不支援 在串流中加入絕對樣本時間戳記,因此此方法

基於上述原因,如要精確查詢 VBR MP3 檔案,唯一方法就是 掃描整個檔案並手動建立時間與位元組的對應 廣告。您可以使用 FLAG_ENABLE_INDEX_SEEKING、 可使用以下指令列:DefaultExtractorsFactory 上設定 setMp3ExtractorFlags。請注意,如果是大型 MP3 檔案,我們無法妥善處理 尤其是當觀眾嘗試在直播即將結束之前 播放器必須等待廣告下載完成,才能開始播放 並且為整個串流建立索引,然後再執行跳轉功能在 ExoPlayer 中 在此例中,我們決定以速度比準確度來最佳化 因此,FLAG_ENABLE_INDEX_SEEKING 預設為停用。

如果您控制正在播放的媒體,強烈建議您使用更多 提供的容器格式 如 MP4我們並未發現任何用途 ,因此 MP3 是最適合的媒體格式。

為什麼影片跳轉的速度很慢?

當播放器跳轉在影片中新的播放位置時,需要執行以下兩項操作: 事物:

  1. 將與新播放位置的對應資料載入緩衝區 (如果這項資料已緩衝處理,可能就不需進行這項程序)。
  2. 清除影片解碼器,然後開始從 I 頁框 (主要畫面格) 解碼 新的播放位置,因為大多數影片都採用影格內編碼 壓縮格式。為確保尋求「準確」 (即 播放剛好從跳轉位置開始播放),則兩個頁框之間 上一個 IFrame 的位置和尋找位置,必須必須解碼並立即解碼 捨棄 (未顯示在畫面上)。

增加 (1) 造成的延遲時間,可增加 或將資料預先快取至磁碟

降低 (2) 造成的延遲可以降低 使用 ExoPlayer.setSeekParameters 或重新編碼影片 產生較多的 I 頁框 (產生較大的輸出檔案)。

為什麼有些 MPEG-TS 檔案無法播放?

部分 MPEG-TS 檔案不含存取單位分隔符號 (AUD)。根據預設 ExoPlayer 仰賴以澳幣來偵測影格邊界,同樣地,有些 MPEG-TS 檔案不含 IDR 主要畫面格。根據預設 ExoPlayer 考慮的主要畫面格。

ExoPlayer 遭系統要求播放內容時,似乎處於緩衝狀態 缺少 AUDs 或 IDR 主要畫面格的 MPEG-TS 檔案。如果需要播放這類檔案 方法是使用 FLAG_DETECT_ACCESS_UNITSFLAG_ALLOW_NON_IDR_KEYFRAMES。這些標記可以DefaultExtractorsFactory使用 setTsExtractorFlags,或 DefaultHlsExtractorFactory使用 建構函式中。 使用 FLAG_DETECT_ACCESS_UNITS 並不會造成任何副作用 相較於以音訊為基礎的影格邊界偵測,計算成本高昂。使用 FLAG_ALLOW_NON_IDR_KEYFRAMES 可能會引發暫時性的視覺毀損 開始播放,並在播放某些 MPEG-TS 檔案後立即跳轉。

為什麼某些 MPEG-TS 檔案沒有字幕?

部分 MPEG-TS 檔案包含 CEA-608 音軌,但未在 因此 ExoPlayer 無法偵測這些中繼資料您可以手動 列出所需的字幕軌 DefaultExtractorsFactory 的子標題格式,包含無障礙功能 可用來在 MPEG-TS 串流中識別這些頻道:

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory()
    .setTsSubtitleFormats(
      listOf(
        Format.Builder()
          .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
          .setAccessibilityChannel(accessibilityChannel)
          // Set other subtitle format info, such as language.
          .build()
      )
    )
val player: Player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory()
        .setTsSubtitleFormats(
            ImmutableList.of(
                new Format.Builder()
                    .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
                    .setAccessibilityChannel(accessibilityChannel)
                    // Set other subtitle format info, such as language.
                    .build()));
Player player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

為何某些 MP4/FMP4 檔案可以正常播放?

部分 MP4/FMP4 檔案包含的編輯清單,是由系統根據 略過、移動或重複樣本清單。ExoPlayer 僅提供部分支援 以套用編輯清單例如延遲或重複取樣群組 會從同步處理樣本開始,但不會截斷音訊樣本或 針對尚未從同步處理樣本開始的編輯,加入片頭媒體。

要是發現某個部分意外遺漏或重複 請嘗試設定 Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTSFragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS,因此 來完全忽略編輯清單這些設定可以DefaultExtractorsFactory 使用 setMp4ExtractorFlags,或 setFragmentedMp4ExtractorFlags

為什麼部分串流因 HTTP 回應代碼 301 或 302 失敗?

HTTP 回應代碼 301 和 302 都代表重新導向。簡短說明 可以在 Wikipedia 上找到。當 ExoPlayer 發出要求並收到 傳回狀態碼為 301 或 302 的回應,通常會追蹤重新導向的 然後依正常方式開始播放預設不會達成這個目標的情況 適用於跨通訊協定重新導向跨通訊協定重新導向 從 HTTPS 到 HTTP,反之亦然 (在 通訊協定)。您可以使用 wget 指令列工具,如下所示:

wget "https://yourserver.com/test.mp3" 2>&1  | grep Location

輸出內容應如下所示:

Location: https://second.com/test.mp3 [following]
Location: http://third.com/test.mp3 [following]

本例有兩個重新導向。第一個重新導向來自 https://yourserver.com/test.mp3https://second.com/test.mp3。兩者 因此並非跨通訊協定重新導向。第二個重新導向是 https://second.com/test.mp3http://third.com/test.mp3。這個重新導向 因此是一種跨通訊協定重新導向ExoPlayer 不會 按照這個重新導向的預設設定進行設定,表示播放失敗。

如有需要,您可以設定 ExoPlayer 以追蹤跨通訊協定重新導向 您可以為 App Engine 叢集中使用的 DefaultHttpDataSource.Factory 執行個體 應用程式。瞭解如何選取及設定網路堆疊 請按這裡

為什麼部分串流會因為 UnrecognizedInputFormatException 而失敗?

這個問題與下列表單播放失敗有關:

UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.

上述失敗原因有兩種。最常見的原因是 您嘗試播放 DASH (mpd)、HLS (m3u8) 或 SmoothStreaming (ism、isml) 但播放器會嘗試以漸進式串流方式播放。為了玩這個遊戲 串流,您必須依附於相應的 ExoPlayer 模組。如果 串流 URI 的結尾不是標準副檔名,您也可以 MimeTypes.APPLICATION_MPDMimeTypes.APPLICATION_M3U8MimeTypes.APPLICATION_SSsetMimeType 中的 MediaItem.Builder 指定串流類型

第二個較少見的原因,是 ExoPlayer 不支援容器 嘗試播放的媒體格式在此情況下,失敗作業是 不過,歡迎您隨時將功能要求提交給我們的 Issue Tracker,包括容器格式和測試串流的詳細資料。 提交新的功能要求前,請先搜尋現有的功能要求。

為什麼 setPlaybackParameters 無法在部分裝置上正常運作?

在 Android M 以下版本執行應用程式的偵錯版本時, 出現延遲情況、可聽的構件和高 CPU 使用率 setPlaybackParameters API。這是因為最佳化程序 對這個 API 而言很重要的偵錯版本,會在這些位置執行的偵錯版本停用 最新推出的 Android 版本

請特別留意,這個問題只會影響偵錯版本。「不會」 會影響發布子版本,但最佳化功能一律會啟用。因此, 您為使用者提供的版本不會受到影響。

什麼是「在錯誤的執行緒上存取播放器」錯誤代表什麼意思?

請參閱開始使用頁面的「執行緒注意事項」。

如何修正「非預期的狀態行:ICY 200 正常」?

如果伺服器回應包含 ICY 狀態行, 而不是符合 HTTP 要求ICY 狀態線已淘汰, 因此,如果您控制伺服器,請進行更新,以便提供 表示符合 HTTP 規定的回應若無法執行此操作,請使用 ExoPlayer OkHttp 程式庫能夠處理 ICY,因此問題已解決 狀態行。

如何查詢正在播放的串流內容屬於直播?

您可以查詢玩家的 isCurrentWindowLive 方法。此外,您 可以前往 isCurrentWindowDynamic 確認視窗是否動態 (也就是仍在隨時間更新)。

如何在應用程式背景執行時持續播放音訊?

請按照下列步驟操作,確保應用程式在運作期間仍可繼續播放音訊 背景:

  1. 您需要有執行中的前景服務。這樣可以避免系統 包括終止程序、釋出資源
  2. 您必須保留WifiLockWakeLock。這樣可確保 系統會讓 Wi-Fi 無線電和 CPU 保持啟用。建議您透過 ExoPlayer呼叫 setWakeMode,系統會自動 獲取並釋放必要的鎖定。

如果未使用 setWakeMode,請務必釋出鎖定並停止 即可停止播放服務

為什麼 ExoPlayer 支援我的內容,但 ExoPlayer Cast 程式庫不支援?

這可能是因為你嘗試播放的內容不是 CORS 已啟用Cast 架構規定內容必須在 才能播放。

為什麼內容無法播放,卻沒有出現錯誤?

您用來播放內容的裝置可能不支援 支援特定媒體範例格式就能輕鬆確認 將 EventLogger 做為播放器的事件監聽器,並尋找線條 類似 Logcat 中的以下程式碼:

[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE

NO_UNSUPPORTED_TYPE 表示裝置無法將媒體解碼 mimeType 指定的範例格式。請參閱 Android 媒體格式 說明文件,瞭解支援的範例格式。如何取得 載入及用於播放的解碼程式庫?

如何取得要載入並用於播放的解碼程式庫?

  • 大部分的解碼器程式庫都設有手動檢查及建構依附元件的步驟 請確認您已按照 README 文件裡相關圖書館的步驟進行。 以 ExoPlayer FFmpeg 程式庫為例 libraries/decoder_ffmpeg/README.md 中的指示,包括傳遞 設定旗標,為要播放的任何格式啟用解碼器
  • 如果程式庫內含原生程式碼,請確認你使用 使用 README 版本中指定的 Android NDK 版本,並留意 發生任何錯誤。您應該會看到 .so 這些檔案會出現在每個 Pod 路徑的 libs 子目錄中 支援的架構。
  • 如要使用試用版應用程式中的程式庫試用播放功能,請參閱 啟用隨附解碼器查看 README 檔的圖書館 以瞭解如何從自己的應用程式使用程式庫。
  • 如果您使用 DefaultRenderersFactory,應該會看到資訊層級 記錄行,例如「Loaded FfmpegAudioRenderer」。 如果缺少這個程式碼,請確認應用程式的依附元件 解碼器。
  • 如果您在 Logcat 中看到來自 LibraryLoader 的警告層級記錄,則 表示無法載入程式庫的原生元件。如果這是 會發生這種情形,請檢查是否已正確遵守程式庫 README 檔案中的步驟 按照指示執行時,系統並未輸出任何錯誤。

如果您還是無法使用解碼程式庫,請查看 Media3 Issue Tracker 有助您找出近期相關問題。如有需要 這和建構程式庫原生部分有關 加入執行 README 操作說明中的完整命令行輸出內容,協助我們 診斷問題。

我可以直接透過 ExoPlayer 播放 YouTube 影片嗎?

不可以,ExoPlayer 無法播放 YouTube 影片,例如以下格式的網址: https://www.youtube.com/watch?v=...。請改用 YouTube IFrame Player API, 才能在 Android 裝置上播放 YouTube 影片

影片播放斷斷續續

舉例來說,如果裝置無法正確解碼內容,例如 內容位元率或解析度超出裝置功能。您可能需要 並利用品質不佳的內容在這類裝置上獲得良好效能。

如果搭載 Android 版本的裝置發生影片延遲問題 Android 6.0 (API 級別 23) 至 Android 11 (API 級別 30) 及以上版本: 尤其是播放受到 DRM 保護或高影格速率的內容時 啟用非同步緩衝區佇列

不穩定的 API Lint 錯誤

Media3 保證部分 API 介面的二進位檔相容性。 「無法」保證二進位檔相容性的部分會標示為 @UnstableApi。為了清楚區分實際情況 除非 API 符號加上 @OptIn 註解,否則 API 符號會產生 Lint 錯誤。

@UnstableApi 註解並不表示 API 的品質或效能,只是表示其不是「API 凍結」。

您有兩種方式可以處理不穩定的 API Lint 錯誤:

  • 改用可達到相同結果的穩定 API。
  • 繼續使用不穩定的 API,並使用 @OptIn 為用量加上註解,如下所示: 。
新增 @OptIn 註解

Android Studio 可協助您新增註解:

螢幕截圖:如何新增參與意願選項註解
圖 2:使用 Android Studio 新增 @androidx.annotations.OptIn 註解。

您也可以在 Kotlin 中,手動為特定使用情況網站加上註解:

import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi

@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }

您也可以在 Java 中執行下列動作:

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }

可透過新增 package-info.java 檔案選擇加入整個套件:

@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

使用者可以選擇加入整個專案,方法是在專案中隱藏特定 Lint 錯誤 lint.xml 檔案

 <?xml version="1.0" encoding="utf-8"?>
 <lint>
   <issue id="UnsafeOptInUsageError">
     <option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
   </issue>
 </lint>

還有不該使用的 kotlin.OptIn 註解。是 必須使用 androidx.annotation.OptIn 註解。