Khắc phục sự cố


Khắc phục lỗi "Không cho phép lưu lượng truy cập HTTP qua văn bản thô"

Lỗi này sẽ xảy ra nếu ứng dụng của bạn yêu cầu lưu lượng truy cập HTTP dạng văn bản thô (tức là http:// thay vì https://) khi Cấu hình bảo mật mạng của ứng dụng không cho phép. Nếu ứng dụng của bạn nhắm đến Android 9 (API cấp 28) trở lên, thì lưu lượng truy cập HTTP qua văn bản thô sẽ bị vô hiệu hoá theo cấu hình mặc định.

Nếu ứng dụng của bạn cần xử lý lưu lượng truy cập HTTP qua văn bản thô, thì bạn cần sử dụng Cấu hình bảo mật mạng cho phép. Xem tài liệu về bảo mật mạng của Android để biết thông tin chi tiết. Để bật tất cả lưu lượng truy cập HTTP qua văn bản thô, bạn chỉ cần thêm android:usesCleartextTraffic="true" vào phần tử application của AndroidManifest.xml trong ứng dụng.

Ứng dụng minh hoạ ExoPlayer sử dụng Cấu hình bảo mật mạng mặc định, vì vậy, ứng dụng này không cho phép lưu lượng truy cập HTTP qua văn bản thô. Bạn có thể bật chế độ này bằng cách làm theo hướng dẫn ở trên.

Khắc phục lỗi "SSLhandshakeException", "CertPathValidatorException" và "ERR_CERT_AUTHORITY_INVALID"

SSLHandshakeException, CertPathValidatorExceptionERR_CERT_AUTHORITY_INVALID đều chỉ ra sự cố với chứng chỉ SSL của máy chủ. Những lỗi này không chỉ xảy ra với ExoPlayer. Hãy xem tài liệu về SSL của Android để biết thêm thông tin chi tiết.

Tại sao một số tệp nội dung nghe nhìn không thể tìm kiếm được?

Theo mặc định, ExoPlayer không hỗ trợ tìm kiếm trong nội dung nghe nhìn, trong đó phương pháp duy nhất để thực hiện các thao tác tìm kiếm chính xác là để người chơi quét và lập chỉ mục toàn bộ tệp. ExoPlayer coi các tệp như vậy là không thể tìm kiếm. Hầu hết các định dạng vùng chứa nội dung nghe nhìn hiện đại đều bao gồm siêu dữ liệu để tìm kiếm (chẳng hạn như chỉ mục mẫu), có thuật toán tìm kiếm được xác định rõ (ví dụ: tìm kiếm bằng hai phần nội suy cho Ogg) hoặc cho biết nội dung của các vùng chứa đó là có tốc độ bit không đổi. ExoPlayer có thể sử dụng và hỗ trợ thao tác tìm kiếm hiệu quả trong những trường hợp như vậy.

Nếu cần tìm kiếm nhưng lại không thể tìm thấy nội dung nghe nhìn, bạn nên chuyển đổi nội dung của mình để sử dụng định dạng vùng chứa phù hợp hơn. Đối với các tệp MP3, ADTS và AMR, bạn cũng có thể bật tính năng tìm kiếm với giả định rằng các tệp có tốc độ bit không đổi, như mô tả tại đây.

Tại sao tính năng tìm kiếm không chính xác trong một số tệp MP3?

Về cơ bản, các tệp MP3 có tốc độ bit biến thiên (VBR) không phù hợp với các trường hợp sử dụng đòi hỏi chế độ tua chính xác. Có hai lý do dẫn đến trường hợp này:

  1. Đối với tính năng tìm kiếm chính xác, định dạng vùng chứa sẽ cung cấp mối liên kết chính xác từ thời gian đến byte trong tiêu đề. Cách liên kết này cho phép người chơi liên kết thời gian tua được yêu cầu với độ lệch byte tương ứng và bắt đầu yêu cầu, phân tích cú pháp và phát nội dung đa phương tiện từ độ lệch đó. Rất tiếc, các tiêu đề có sẵn để chỉ định ánh xạ này trong MP3 (chẳng hạn như tiêu đề XING) thường không chính xác.
  2. Đối với các định dạng vùng chứa không cung cấp liên kết thời gian với byte chính xác (hoặc bất kỳ liên kết thời gian nào với byte), bạn vẫn có thể tìm chính xác nếu vùng chứa chứa dấu thời gian mẫu tuyệt đối trong luồng. Trong trường hợp này, người chơi có thể ánh xạ thời gian tìm kiếm với kết quả dự đoán chính xác nhất về độ lệch byte tương ứng, bắt đầu yêu cầu nội dung nghe nhìn từ độ lệch đó, phân tích cú pháp dấu thời gian của mẫu tuyệt đối đầu tiên và thực hiện hiệu quả việc tìm kiếm nhị phân có hướng dẫn trên nội dung nghe nhìn cho đến khi tìm thấy mẫu phù hợp. Rất tiếc, MP3 không bao gồm dấu thời gian mẫu tuyệt đối trong luồng, vì vậy, phương pháp này không thể áp dụng.

Vì những lý do này, cách duy nhất để thực hiện việc tìm kiếm chính xác trong tệp VBR MP3 là quét toàn bộ tệp và tạo ánh xạ thời gian đến byte trong trình phát theo cách thủ công. Bạn có thể bật chiến lược này bằng cách dùng FLAG_ENABLE_INDEX_SEEKING. Bạn có thể đặt chiến lược này trên DefaultExtractorsFactory bằng cách dùng setMp3ExtractorFlags. Lưu ý rằng tỷ lệ mở rộng sẽ không tốt đối với các tệp MP3 lớn, cụ thể là nếu người dùng cố gắng tìm đến gần cuối luồng ngay sau khi bắt đầu phát, điều này yêu cầu trình phát phải đợi cho đến khi được tải xuống và lập chỉ mục toàn bộ luồng trước khi thực hiện tìm kiếm. Trong ExoPlayer, chúng tôi đã quyết định tối ưu hoá để đảm bảo tốc độ thay vì độ chính xác trong trường hợp này, và do đó, FLAG_ENABLE_INDEX_SEEKING sẽ bị tắt theo mặc định.

Nếu điều khiển nội dung nghe nhìn đang phát, bạn nên sử dụng định dạng vùng chứa phù hợp hơn, chẳng hạn như MP4. Không có trường hợp sử dụng nào mà chúng tôi biết rõ rằng MP3 là lựa chọn tốt nhất cho định dạng nội dung nghe nhìn.

Tại sao chế độ tua trong video của tôi bị chậm?

Khi tìm cách đến một vị trí phát mới trong một video, trình phát cần thực hiện 2 việc:

  1. Tải dữ liệu tương ứng với vị trí phát mới vào vùng đệm (có thể không cần thiết nếu dữ liệu này đã được lưu vào vùng đệm).
  2. Xoá bộ giải mã video và bắt đầu giải mã từ khung hình chữ I (khung hình chính) trước vị trí phát mới, do phương thức mã hoá trong khung hình được hầu hết các định dạng nén video sử dụng. Để đảm bảo hoạt động tìm kiếm chính xác (nghĩa là quá trình phát bắt đầu chính xác ở vị trí tìm kiếm), bạn cần giải mã và loại bỏ tất cả khung hình giữa khung hình chữ I trước và vị trí tìm kiếm (mà không cần hiện trên màn hình).

Bạn có thể giảm thiểu độ trễ do (1) tạo ra bằng cách tăng lượng dữ liệu được trình phát lưu vào bộ đệm trong bộ nhớ hoặc lưu trước dữ liệu vào bộ nhớ đệm vào ổ đĩa.

Bạn có thể giảm thiểu độ trễ mà (2) mang lại bằng cách giảm độ chính xác của quá trình tua bằng cách sử dụng ExoPlayer.setSeekParameters hoặc mã hoá lại video để có các khung hình chữ I thường xuyên hơn (dẫn đến tệp đầu ra lớn hơn).

Tại sao một số tệp MPEG-TS không phát được?

Một số tệp MPEG-TS không chứa dấu phân cách đơn vị truy cập (AUD). Theo mặc định, ExoPlayer dựa vào AUD để phát hiện ranh giới khung hình với chi phí thấp. Tương tự, một số tệp MPEG-TS không chứa khung hình chính IDR. Theo mặc định, đây là những loại khung hình chính duy nhất được ExoPlayer cân nhắc.

ExoPlayer có vẻ như bị kẹt ở trạng thái lưu vào bộ đệm khi được yêu cầu phát một tệp MPEG-TS thiếu khung hình chính AUD hoặc IDR. Nếu cần phát các tệp như vậy, bạn có thể thực hiện việc này bằng cách sử dụng FLAG_DETECT_ACCESS_UNITSFLAG_ALLOW_NON_IDR_KEYFRAMES tương ứng. Những cờ này có thể được đặt trên DefaultExtractorsFactory bằng setTsExtractorFlags hoặc trên DefaultHlsExtractorFactory bằng hàm khởi tạo. Việc sử dụng FLAG_DETECT_ACCESS_UNITS không có tác dụng phụ nào khác ngoài việc tiêu tốn tài nguyên tính toán so với tính năng phát hiện ranh giới khung hình dựa trên AUD. Việc sử dụng FLAG_ALLOW_NON_IDR_KEYFRAMES có thể dẫn đến lỗi hình ảnh tạm thời khi bắt đầu phát và ngay sau khi tua khi phát một số tệp MPEG-TS.

Tại sao không tìm thấy phụ đề trong một số tệp MPEG-TS?

Một số tệp MPEG-TS bao gồm các bản nhạc CEA-608 nhưng không khai báo các tệp này trong siêu dữ liệu vùng chứa, vì vậy, ExoPlayer không thể phát hiện các tệp này. Bạn có thể chỉ định bất kỳ bản phụ đề nào theo cách thủ công bằng cách cung cấp danh sách các định dạng phụ đề dự kiến cho DefaultExtractorsFactory, bao gồm cả các kênh hỗ trợ tiếp cận có thể dùng để xác định các định dạng đó trong luồng 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();

Tại sao một số tệp MP4/FMP4 phát không chính xác?

Một số tệp MP4/FMP4 chứa danh sách chỉnh sửa ghi lại tiến trình của nội dung đa phương tiện bằng cách bỏ qua, di chuyển hoặc lặp lại danh sách mẫu. ExoPlayer hỗ trợ một phần việc áp dụng danh sách chỉnh sửa. Ví dụ: phương thức này có thể trì hoãn hoặc lặp lại các nhóm mẫu bắt đầu trên một mẫu đồng bộ hoá, nhưng không cắt bớt các mẫu âm thanh hoặc nội dung nghe nhìn đầu video cho các nội dung chỉnh sửa không bắt đầu trên mẫu đồng bộ hoá.

Nếu bạn thấy một phần nội dung nghe nhìn bị thiếu hoặc lặp lại đột ngột, hãy thử đặt Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS hoặc FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS. Thao tác này sẽ khiến trình trích xuất bỏ qua hoàn toàn danh sách chỉnh sửa. Bạn có thể đặt chúng trên DefaultExtractorsFactory bằng setMp4ExtractorFlags hoặc setFragmentedMp4ExtractorFlags.

Tại sao một số luồng bị lỗi với mã phản hồi HTTP 301 hoặc 302?

Cả mã phản hồi HTTP 301 và 302 đều chỉ báo chuyển hướng. Bạn có thể xem nội dung mô tả ngắn gọn trên Wikipedia. Khi ExoPlayer đưa ra yêu cầu và nhận được phản hồi có mã trạng thái 301 hoặc 302, thì thông thường, ExoPlayer sẽ tuân theo lệnh chuyển hướng và bắt đầu phát như bình thường. Một trường hợp mà điều này không xảy ra theo mặc định là chuyển hướng giữa nhiều giao thức. Chuyển hướng giữa nhiều giao thức là hoạt động chuyển hướng từ HTTPS sang HTTP hoặc ngược lại (hoặc ít phổ biến hơn là giữa một cặp giao thức khác). Bạn có thể kiểm tra xem một URL có gây ra lệnh chuyển hướng giữa nhiều giao thức hay không bằng cách sử dụng công cụ dòng lệnh wget như sau:

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

Kết quả đầu ra sẽ có dạng như sau:

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

Trong ví dụ này, có hai lệnh chuyển hướng. Lệnh chuyển hướng đầu tiên từ https://yourserver.com/test.mp3 đến https://second.com/test.mp3. Cả hai đều là HTTPS nên đây không phải là hoạt động chuyển hướng giữa nhiều giao thức. Lệnh chuyển hướng thứ hai là từ https://second.com/test.mp3 đến http://third.com/test.mp3. Phương thức này chuyển hướng từ HTTPS sang HTTP cũng như chuyển hướng giữa nhiều giao thức. ExoPlayer sẽ không đi theo lệnh chuyển hướng này trong cấu hình mặc định, nghĩa là quá trình phát sẽ không thành công.

Nếu cần, bạn có thể định cấu hình ExoPlayer để tuân theo các lệnh chuyển hướng giữa nhiều giao thức khi tạo thực thể cho các thực thể DefaultHttpDataSource.Factory được dùng trong ứng dụng của bạn. Tìm hiểu về cách chọn và định cấu hình ngăn xếp mạng tại đây.

Tại sao một số luồng bị lỗi với UnRecognizeInputFormatException?

Câu hỏi này liên quan đến các lỗi phát lại ở dạng sau:

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

Có hai nguyên nhân có thể dẫn đến lỗi này. Nguyên nhân phổ biến nhất là do bạn đang cố phát nội dung DASH (mpd), HLS (m3u8) hoặc SmoothStreaming (ism, isml), nhưng trình phát cố gắng phát nội dung dưới dạng luồng tăng dần. Để phát những luồng như vậy, bạn phải phụ thuộc vào mô-đun ExoPlayer tương ứng. Trong trường hợp URI luồng không kết thúc bằng đuôi tệp tiêu chuẩn, bạn cũng có thể chuyển MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 hoặc MimeTypes.APPLICATION_SS đến setMimeType của MediaItem.Builder để chỉ định rõ loại luồng.

Nguyên nhân thứ hai ít phổ biến hơn là ExoPlayer không hỗ trợ định dạng vùng chứa của nội dung nghe nhìn mà bạn đang cố phát. Trong trường hợp này, lỗi vẫn hoạt động như dự kiến. Tuy nhiên, vui lòng gửi yêu cầu về tính năng tới công cụ theo dõi lỗi của chúng tôi, bao gồm cả thông tin chi tiết về định dạng vùng chứa và luồng kiểm thử. Vui lòng tìm kiếm một yêu cầu về tính năng hiện có trước khi gửi một yêu cầu mới.

Tại sao setPlaybackParameters không hoạt động đúng cách trên một số thiết bị?

Khi chạy một bản gỡ lỗi của ứng dụng trên Android M trở xuống, bạn có thể gặp phải vấn đề hiệu suất bị giật, cấu phần phần mềm âm thanh và mức sử dụng CPU cao khi sử dụng API setPlaybackParameters. Lý do là tính năng tối ưu hoá quan trọng đối với API này đã bị vô hiệu hoá đối với các bản gỡ lỗi chạy trên các phiên bản Android này.

Điều quan trọng cần lưu ý là vấn đề này chỉ ảnh hưởng đến các bản gỡ lỗi. Tính năng này không ảnh hưởng đến các bản phát hành có tính năng tối ưu hoá sẽ luôn bật. Do đó, các bản phát hành mà bạn cung cấp cho người dùng cuối sẽ không chịu ảnh hưởng của vấn đề này.

Lỗi "Trình phát được truy cập trên chuỗi không đúng" nghĩa là gì?

Xem phần Lưu ý về việc tạo chuỗi trên trang bắt đầu.

Làm cách nào để khắc phục lỗi "Dòng trạng thái không mong muốn: ICY 200 OK"?

Sự cố này có thể xảy ra nếu phản hồi của máy chủ bao gồm một dòng trạng thái ICY thay vì một dòng tương thích HTTP. Các dòng trạng thái ICY không được dùng nữa và không nên được sử dụng. Vì vậy, nếu kiểm soát máy chủ, bạn nên cập nhật máy chủ đó để cung cấp phản hồi tuân thủ HTTP. Nếu bạn không thể thực hiện việc này thì việc sử dụng thư viện ExoPlayer OkHttp sẽ giúp giải quyết vấn đề này vì thư viện này có thể xử lý các dòng trạng thái ICY một cách chính xác.

Làm cách nào để truy vấn xem sự kiện phát trực tiếp đang phát có phải là sự kiện phát trực tiếp hay không?

Bạn có thể truy vấn phương thức isCurrentWindowLive của người chơi. Ngoài ra, bạn có thể kiểm tra isCurrentWindowDynamic để tìm hiểu xem cửa sổ đó có động (nghĩa là vẫn cập nhật theo thời gian).

Làm thế nào để tiếp tục phát âm thanh khi ứng dụng của tôi chạy ở chế độ nền?

Hãy làm theo các bước sau để đảm bảo việc tiếp tục phát âm thanh khi ứng dụng của bạn ở chế độ nền:

  1. Bạn cần có một dịch vụ trên nền trước đang chạy. Điều này ngăn hệ thống loại bỏ quy trình của bạn để giải phóng tài nguyên.
  2. Bạn cần giữ WifiLockWakeLock. Những việc này giúp đảm bảo hệ thống giữ cho đài phát Wi-Fi và CPU luôn hoạt động. Điều này có thể dễ dàng thực hiện nếu sử dụng ExoPlayer bằng cách gọi setWakeMode. Quá trình này sẽ tự động thu nạp và mở khoá cần thiết vào đúng thời điểm.

Bạn cần phải nhả khoá (nếu không sử dụng setWakeMode) và dừng dịch vụ ngay khi không phát âm thanh nữa.

Tại sao ExoPlayer hỗ trợ nội dung của tôi nhưng thư viện ExoPlayer Cast lại không hỗ trợ?

Có thể nội dung mà bạn đang cố phát chưa được bật CORS. Khung Truyền yêu cầu bạn phải bật nội dung CORS để có thể phát nội dung đó.

Tại sao nội dung không phát được nhưng không xuất hiện lỗi?

Có thể thiết bị mà bạn đang phát nội dung không hỗ trợ một định dạng mẫu nội dung nghe nhìn cụ thể. Bạn có thể dễ dàng xác nhận điều này bằng cách thêm EventLogger làm trình nghe cho trình phát và tìm một dòng tương tự như dòng này trong Logcat:

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

NO_UNSUPPORTED_TYPE có nghĩa là thiết bị không thể giải mã định dạng mẫu nội dung nghe nhìn do mimeType chỉ định. Xem tài liệu về định dạng nội dung đa phương tiện của Android để biết thông tin về các định dạng mẫu được hỗ trợ. Làm cách nào để tải thư viện giải mã và dùng để phát lại? cũng có thể hữu ích.

Làm cách nào để thư viện giải mã tải và dùng để phát lại?

  • Hầu hết các thư viện bộ giải mã đều có các bước thủ công để kiểm tra và xây dựng các phần phụ thuộc, vì vậy, hãy đảm bảo bạn đã làm theo các bước trong tệp README cho thư viện liên quan. Ví dụ: đối với thư viện ExoPlayer FFmpeg, bạn cần làm theo hướng dẫn trong Library/decoder_ffmpeg/README.md, bao gồm cả việc truyền cờ cấu hình để bật bộ giải mã cho mọi định dạng bạn muốn phát.
  • Đối với các thư viện có mã gốc, hãy đảm bảo bạn đang sử dụng đúng phiên bản Android NDK như được chỉ định trong tệp README, đồng thời chú ý mọi lỗi xuất hiện trong quá trình định cấu hình và xây dựng. Bạn sẽ thấy các tệp .so xuất hiện trong thư mục con libs thuộc đường dẫn của thư viện cho từng cấu trúc được hỗ trợ sau khi làm theo các bước trong tệp README.
  • Để thử phát lại bằng thư viện trong ứng dụng minh hoạ, hãy xem bài viết bật bộ giải mã đi kèm. Hãy xem phần README cho thư viện để biết hướng dẫn sử dụng thư viện trong ứng dụng của riêng bạn.
  • Nếu đang sử dụng DefaultRenderersFactory, bạn sẽ thấy một dòng nhật ký ở cấp thông tin, chẳng hạn như "Đã tải FfmpegAudioRenderer" trong Logcat khi bộ giải mã tải. Nếu thiếu dữ liệu đó, hãy đảm bảo ứng dụng có phần phụ thuộc vào thư viện giải mã.
  • Nếu bạn thấy nhật ký ở cấp cảnh báo từ LibraryLoader trong Logcat, thì điều này cho biết rằng không thể tải thành phần gốc của thư viện. Nếu điều này xảy ra, hãy kiểm tra xem bạn đã làm theo các bước trong tệp README của thư viện đúng cách hay chưa và đảm bảo không có lỗi nào xảy ra trong khi làm theo hướng dẫn.

Nếu bạn vẫn gặp sự cố khi sử dụng thư viện giải mã, vui lòng kiểm tra công cụ theo dõi lỗi Media3 để biết mọi vấn đề liên quan gần đây. Nếu bạn cần báo một vấn đề mới và vấn đề đó liên quan đến việc xây dựng phần gốc của thư viện, vui lòng đưa toàn bộ kết quả dòng lệnh vào hoạt động chạy hướng dẫn README để giúp chúng tôi chẩn đoán vấn đề đó.

Tôi có thể phát trực tiếp video trên YouTube bằng ExoPlayer không?

Không, ExoPlayer không thể phát video trên YouTube, chẳng hạn như URL có dạng https://www.youtube.com/watch?v=.... Thay vào đó, bạn nên sử dụng API Trình phát Khung nội dung của YouTube. Đây là cách chính thức để phát video YouTube trên Android.

Quá trình phát video bị gián đoạn

Chẳng hạn, thiết bị có thể không giải mã được nội dung đủ nhanh nếu tốc độ bit hoặc độ phân giải của nội dung vượt quá khả năng của thiết bị. Có thể bạn cần phải sử dụng nội dung có chất lượng thấp hơn để đạt được hiệu suất tốt trên các thiết bị như vậy.

Nếu video của bạn bị gián đoạn trên thiết bị chạy phiên bản Android từ Android 6.0 (API cấp 23) cho đến Android 11 (API cấp 30) và bao gồm cả Android 11 (API cấp 30), đặc biệt là khi phát nội dung được bảo vệ bằng DRM hoặc nội dung có tốc độ khung hình cao, bạn có thể thử bật tính năng xếp hàng đợi bộ đệm không đồng bộ.