Rozwiązywanie problemów


Naprawianie błędów „Niedozwolony ruch HTTP Cleartext”

Ten błąd występuje, jeśli Twoja aplikacja żąda ruchu HTTP nieszyfrowanego (czyli http:// zamiast https://), gdy jej konfiguracja zabezpieczeń sieci na to nie zezwala. Jeśli Twoja aplikacja jest kierowana na Androida 9 (poziom interfejsu API 28) lub nowszego, ruch Cleartext HTTP jest domyślnie wyłączony.

Jeśli Twoja aplikacja ma obsługiwać ruch HTTP nieszyfrowany, musisz użyć konfiguracji zabezpieczeń sieci, która na to zezwala. Więcej informacji znajdziesz w dokumentacji dotyczącej zabezpieczeń sieciowych Androida. Aby włączyć cały ruch HTTP nieszyfrowany, wystarczy dodać android:usesCleartextTraffic="true" do elementu application AndroidManifest.xml aplikacji.

Aplikacja demonstracyjna ExoPlayer korzysta z domyślnej konfiguracji zabezpieczeń sieci, więc nie zezwala na ruch HTTP nieszyfrowany. Aby go włączyć, wykonaj czynności opisane powyżej.

Usuwanie błędów „SSLHandshakeException”, „CertPathValidatorException” i „ERR_CERT_AUTHORITY_INVALID”

SSLHandshakeException, CertPathValidatorException i ERR_CERT_AUTHORITY_INVALID wskazują na problem z certyfikatem SSL serwera. Te błędy nie dotyczą konkretnego odtwarzacza ExoPlayer. Więcej informacji znajdziesz w dokumentacji protokołu SSL w Androidzie.

Dlaczego niektórych plików multimedialnych nie można przeszukiwać?

Domyślnie ExoPlayer nie obsługuje wyszukiwania multimediów, gdy jedyną metodą wykonania dokładnej operacji wyszukiwania jest przeskanowanie i zindeksowanie całego pliku przez odtwarzacz. ExoPlayer uznaje takie pliki za niemożliwe do wyszukania. Większość nowoczesnych formatów kontenerów multimediów zawiera metadane do wyszukiwania (takie jak indeks próbki), ma dobrze zdefiniowany algorytm wyszukiwania (np. wyszukiwanie dwusekcji w przypadku Ogg) lub wskazuje, że ich zawartość ma stałą szybkość transmisji bitów. ExoPlayer może w takich przypadkach wykorzystać skuteczne operacje wyszukiwania.

Jeśli potrzebujesz takich multimediów, ale nie możesz ich znaleźć, przekonwertuj treści na bardziej odpowiedni format kontenera. W przypadku plików MP3, ADTS i AMR możesz też włączyć przewijanie przy założeniu, że pliki mają stałą szybkość transmisji bitów, jak opisano tutaj.

Dlaczego wyszukiwanie w niektórych plikach MP3 jest niedokładne?

Pliki MP3 o zmiennej szybkości transmisji bitów (VBR) zasadniczo nie nadają się do zastosowań, które wymagają dokładnego wyszukiwania. Dzieje się tak z dwóch powodów:

  1. Aby umożliwić dokładne wyszukiwanie, format kontenera zapewni w nagłówku precyzyjne mapowanie czasu na bajty. To mapowanie pozwala odtwarzaczowi zmapować żądany czas wyszukiwania na odpowiednie przesunięcie bajtowe i rozpoczynać żądania, analizowanie i odtwarzanie multimediów z tego przesunięcia. Nagłówki dostępne do określenia tego mapowania w formacie MP3 (np. nagłówki XING) są często zniekształcone.
  2. W przypadku formatów kontenerów, które nie zapewniają dokładnego mapowania czasu na bajty (lub takiego mapowania w ogóle), możliwe jest dokładne przeszukiwanie, jeśli kontener zawiera w strumieniu bezwzględne sygnatury czasowe bezwzględnej próbki. W takim przypadku odtwarzacz może zmapować czas wyszukiwania na jak najtrafniejszą wartość przesunięcia bajtów, rozpocząć żądanie multimediów z tego przesunięcia, przeanalizować bezwzględną sygnaturę czasową próbki i skutecznie przeprowadzić wyszukiwanie binarne do multimediów, aż znajdzie odpowiednią próbkę. Plik MP3 nie zawiera bezwzględnych sygnatur czasowych próbki, więc takie podejście nie jest możliwe.

Z tych powodów jedynym sposobem na dokładne przeszukiwanie pliku VBR MP3 jest przeskanowanie całego pliku i ręczne utworzenie mapowania czasu do bajtów w odtwarzaczu. Tę strategię można włączyć za pomocą parametru FLAG_ENABLE_INDEX_SEEKING, który można ustawić w DefaultExtractorsFactory przy użyciu setMp3ExtractorFlags. Pamiętaj, że nie skaluje się dobrze w przypadku dużych plików MP3, zwłaszcza jeśli użytkownik próbuje dotrzeć do końca strumienia tuż po rozpoczęciu odtwarzania, co oznacza, że przed rozpoczęciem wyszukiwania odtwarzacz musi poczekać, aż pobierze i zindeksuje cały strumień. W narzędziu ExoPlayer zdecydowaliśmy się na optymalizację pod kątem szybkości, a nie dokładności. Dlatego parametr FLAG_ENABLE_INDEX_SEEKING jest domyślnie wyłączony.

Jeśli masz kontrolę nad odtwarzanymi multimediami, zalecamy korzystanie z bardziej odpowiedniego formatu kontenera, np. MP4. Nie wiemy, że nie ma przypadków użycia, w których MP3 to najlepszy wybór formatu multimediów.

Dlaczego przewijanie w moim filmie działa wolno?

Gdy odtwarzacz wyszuka nowe miejsce odtwarzania w filmie, musi spełnić 2 czynności:

  1. Wczytaj do bufora dane odpowiadające nowej pozycji odtwarzania (może to nie być konieczne, jeśli dane zostały już zbuforowane).
  2. Ze względu na kodowanie w ramce stosowane w większości formatów kompresji wideo wyczyść dekoder wideo i rozpocznij dekodowanie od elementu IFrame (klatki kluczowej) przed nową pozycją odtwarzania. Aby zagwarantować, że przewijanie jest precyzyjne (czyli odtwarzanie rozpoczyna się dokładnie w pozycji przewijania), wszystkie klatki między poprzedzającym elementem IFrame a pozycją przewijania muszą zostać zdekodowane i natychmiast odrzucone (nie będą widoczne na ekranie).

Czas oczekiwania spowodowany przez działanie (1) można ograniczyć, zwiększając ilość danych zbuforowanych w pamięci przez odtwarzacz lub wstępnie zapisując dane na dysku.

Opóźnienie spowodowane przez wartość (2) można zniwelować, zmniejszając dokładność przewijania za pomocą narzędzia ExoPlayer.setSeekParameters lub ponownie kodując film, aby uzyskać częstsze klatki I (co spowoduje utworzenie większego pliku wyjściowego).

Dlaczego niektórych plików MPEG-TS nie można odtworzyć?

Niektóre pliki MPEG-TS nie zawierają ograniczników jednostki dostępu (AUD). Domyślnie ExoPlayer korzysta z AUD, aby tanio wykrywać granice klatek. Podobnie niektóre pliki MPEG-TS nie zawierają klatek kluczowych IDR. Domyślnie to jedyny typ klatek kluczowych uwzględniany przez ExoPlayer.

Przy próbie odtworzenia pliku MPEG-TS bez klatek kluczowych AUD lub IDR może wystąpić sytuacja, gdy odtwarzacz ExoPlayer zatrzymuje się w stanie buforowania. Jeśli chcesz odtworzyć takie pliki, możesz to zrobić za pomocą odpowiednio FLAG_DETECT_ACCESS_UNITS i FLAG_ALLOW_NON_IDR_KEYFRAMES. Te flagi można ustawić w elemencie DefaultExtractorsFactory za pomocą setTsExtractorFlags lub w elemencie DefaultHlsExtractorFactory za pomocą konstruktora. Korzystanie z funkcji FLAG_DETECT_ACCESS_UNITS nie ma żadnych skutków ubocznych poza używaniem obliczeń obliczeniowych w porównaniu z wykrywaniem granic klatek na podstawie AUD. Użycie funkcji FLAG_ALLOW_NON_IDR_KEYFRAMES może spowodować tymczasowe uszkodzenie obrazu na początku odtwarzania i bezpośrednio po wyszukiwaniu w przypadku niektórych plików MPEG-TS.

Dlaczego w niektórych plikach MPEG-TS nie ma napisów?

Niektóre pliki MPEG-TS zawierają ścieżki CEA-608, ale nie są zadeklarowane w metadanych kontenera, więc ExoPlayer nie może ich wykryć. Możesz ręcznie określić dowolne ścieżki z napisami, podając w interfejsie DefaultExtractorsFactory listę oczekiwanych formatów napisów wraz z kanałami ułatwień dostępu, które pozwolą Ci zidentyfikować je w strumieniu 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();

Dlaczego niektóre pliki MP4/FMP4 odtwarzają się nieprawidłowo?

Niektóre pliki MP4/FMP4 zawierają listy edycji, które przepisują oś czasu multimediów przez pomijanie, przenoszenie lub powtarzanie list przykładów. ExoPlayer częściowo obsługuje stosowanie list edycji. Może na przykład opóźniać lub powtarzać odtwarzanie grup próbek z próbki synchronizacji, ale nie skraca próbek audio ani multimediów przed filmem w przypadku zmian, które nie rozpoczynają się od próbki synchronizacji.

Jeśli zauważysz, że tej części multimediów nieoczekiwanie brakuje lub się powtarza, spróbuj ustawić metodę Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS lub FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS, co spowoduje, że moduł wyodrębniania całkowicie ignoruje listy edycji. Można je ustawić w elemencie DefaultExtractorsFactory za pomocą metody setMp4ExtractorFlags lub setFragmentedMp4ExtractorFlags.

Dlaczego niektóre strumienie kończą się niepowodzeniem z kodem odpowiedzi HTTP 301 lub 302?

Kody odpowiedzi HTTP 301 i 302 wskazują na przekierowanie. Krótkie opisy można znaleźć w Wikipedii. Gdy ExoPlayer wyśle żądanie i otrzyma odpowiedź z kodem stanu 301 lub 302, zazwyczaj podąża za przekierowaniem i rozpoczyna odtwarzanie w normalny sposób. Jedyny przypadek, w którym nie dzieje się tak domyślnie, to przekierowania między protokołami. Przekierowanie między protokołami to przekierowanie z protokołu HTTPS do HTTP lub odwrotnie (lub rzadziej między innymi parami protokołów). Aby sprawdzić, czy URL powoduje przekierowanie między protokołami, możesz użyć narzędzia wiersza poleceń wget, korzystając z tego narzędzia:

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

Dane wyjściowe powinny wyglądać mniej więcej tak:

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

W tym przykładzie mamy 2 przekierowania. Pierwsze przekierowanie z domeny https://yourserver.com/test.mp3 do https://second.com/test.mp3. Oba protokoły są HTTPS, więc nie jest to przekierowanie między protokołami. Drugie przekierowanie z domeny https://second.com/test.mp3 do witryny http://third.com/test.mp3. Przekierowanie z protokołu HTTPS do HTTP następuje przekierowanie między protokołami. W domyślnej konfiguracji ExoPlayer nie będzie korzystać z tego przekierowania, co oznacza, że odtwarzanie się nie powiedzie.

W razie potrzeby możesz skonfigurować ExoPlayer pod kątem przekierowań między protokołami podczas tworzenia instancji DefaultHttpDataSource.Factory używanych w Twojej aplikacji. Informacje o wybieraniu i konfigurowaniu stosu sieciowego znajdziesz tutaj.

Dlaczego niektóre strumienie kończą się niepowodzeniem z powodu nierozpoznanego InputFormatException?

To pytanie dotyczy błędów odtwarzania w tym formularzu:

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

Taka sytuacja może mieć 2 przyczyny. Najczęstszą przyczyną jest próba odtworzenia treści w formacie DASH (mpd), HLS (m3u8) lub SmoothStreaming (ism, isml), ale odtwarzacz próbuje to odtwarzać jako strumień progresywny. Aby odtwarzać takie strumienie, musisz korzystać z odpowiedniego modułu ExoPlayer. Jeśli identyfikator URI strumienia nie kończy się standardowym rozszerzeniem pliku, możesz też przekazać parametr MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 lub MimeTypes.APPLICATION_SS do setMimeType z MediaItem.Builder, aby wyraźnie określić typ strumienia.

Drugą, rzadszą przyczyną, jest to, że ExoPlayer nie obsługuje formatu kontenera multimediów, które próbujesz odtworzyć. W takim przypadku błąd działa zgodnie z oczekiwaniami, ale możesz przesłać prośbę o dodanie funkcji w naszym narzędziu do śledzenia problemów, podając szczegóły formatu kontenera i strumienia testowego. Zanim prześlesz nową funkcję, poszukaj istniejącej prośby o dodanie funkcji.

Dlaczego na niektórych urządzeniach parametr setPlaybackParameters nie działa prawidłowo?

Podczas uruchamiania kompilacji na potrzeby debugowania na Androidzie M lub starszym podczas korzystania z interfejsu API setPlaybackParameters możesz zauważyć niską wydajność, pojawianie się artefaktów dźwiękowych oraz wysokie wykorzystanie procesora. Dzieje się tak, ponieważ optymalizacja ważna w przypadku tego interfejsu API jest wyłączona w przypadku kompilacji do debugowania działających w tych wersjach Androida.

Pamiętaj, że ten problem dotyczy tylko kompilacji do debugowania. Nie ma wpływu na kompilacje wersji, w których przypadku optymalizacja jest zawsze włączona. Dlatego ten problem nie powinien mieć wpływu na wersje udostępniane użytkownikom.

Co oznaczają błędy „Dostęp do odtwarzacza w niewłaściwym wątku”?

Zobacz Uwagę o wątkach na stronie wprowadzającej.

Jak rozwiązać problem związany z komunikatem „Nieoczekiwana linia stanu: ICY 200 OK”?

Ten problem może wystąpić, jeśli odpowiedź serwera zawiera wiersz stanu ICY, a nie wiersz zgodny z protokołem HTTP. Linie stanu ICY zostały wycofane i nie należy ich używać, więc jeśli kontrolujesz serwer, musisz go zaktualizować, aby dostarczał odpowiedź zgodną z HTTP. Jeśli nie możesz tego zrobić, użyj biblioteki OkHttp ExoPlayer, ponieważ prawidłowo obsługuje ona wiersze stanu ICY.

Jak mogę sprawdzić, czy odtwarzana transmisja jest transmisją na żywo?

Możesz przesłać zapytanie do metody isCurrentWindowLive odtwarzacza. Możesz też sprawdzić isCurrentWindowDynamic, aby dowiedzieć się, czy okno jest dynamiczne (czyli aktualizuje się z upływem czasu).

Jak mogę odtwarzać dźwięk, gdy moja aplikacja działa w tle?

Aby zapewnić ciągłe odtwarzanie dźwięku, gdy Twoja aplikacja działa w tle, wykonaj te czynności:

  1. Musisz mieć aktywną usługę na pierwszym planie. Dzięki temu system nie zamknie Twojego procesu w celu zwolnienia zasobów.
  2. Musisz przechowywać WifiLock i WakeLock. Dzięki temu radio Wi-Fi i procesor pozostaną aktywne. Możesz to łatwo zrobić, używając ExoPlayer, wywołując metodę setWakeMode, która automatycznie uzyska i zwalnia wymagane blokady w odpowiednich momentach.

Pamiętaj, by wyłączyć blokady (jeśli nie używasz setWakeMode) i zatrzymać usługę, gdy tylko dźwięk przestanie się odtwarzać.

Dlaczego ExoPlayer obsługuje moje treści, a biblioteka Cast ExoPlayer nie?

Możliwe, że treść, którą próbujesz odtworzyć, nie jest włączona w edytorze CORS. Aby można było odtwarzać treści, platforma przesyłania wymaga włączenia CORS.

Dlaczego treści nie można odtworzyć, ale nie pojawia się żaden błąd?

Możliwe, że urządzenie, na którym odtwarzasz treści, nie obsługuje określonego formatu próbki multimediów. Można to łatwo sprawdzić, dodając EventLogger jako detektor do odtwarzacza i wyszukując wiersz podobny do tego w Logcat:

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

NO_UNSUPPORTED_TYPE oznacza, że urządzenie nie może zdekodować przykładowego formatu multimediów określonego w polu mimeType. Informacje o obsługiwanych przykładowych formatach znajdziesz w dokumentacji formatów multimediów na Androida. Jak mogę pobrać bibliotekę dekodowania do wczytania i wykorzystać ją do odtwarzania?

Jak mogę załadować bibliotekę dekodowania, aby była używana do odtwarzania?

  • Większość bibliotek dekodera wymaga ręcznego sprawdzania i budowania zależności, dlatego pamiętaj, aby wykonać czynności opisane w pliku README dla odpowiedniej biblioteki. Na przykład w przypadku biblioteki FFmpeg ExoPlayer postępuj zgodnie z instrukcjami podanymi w pliku libraries/decoder_ffmpeg/README.md, w tym przekazując flagi konfiguracji, aby włączyć dekodery dowolnego formatu, który chcesz odtwarzać.
  • W przypadku bibliotek z kodem natywnym sprawdź, czy używasz prawidłowej wersji pakietu Android NDK podanej w pliku README i sprawdź, czy nie wystąpiły błędy podczas konfiguracji i tworzenia. Po wykonaniu czynności opisanych w pliku README w podkatalogu libs ścieżki biblioteki powinny się pojawić pliki .so.
  • Aby wypróbować odtwarzanie przy użyciu biblioteki w aplikacji demonstracyjnej, przeczytaj sekcję o włączaniu połączonych dekoderów. Instrukcje korzystania z biblioteki we własnej aplikacji znajdziesz w pliku README.
  • Jeśli używasz DefaultRenderersFactory, po wczytaniu dekodera powinien być widoczny wiersz logu na poziomie informacji taki jak „Loaded FfmpegAudioRenderer”. Jeśli go brakuje, sprawdź, czy aplikacja korzysta z biblioteki dekodowania.
  • Jeśli w Logcat widzisz logi na poziomie ostrzeżenia z LibraryLoader, oznacza to, że nie udało się wczytać natywnego komponentu biblioteki. W takim przypadku sprawdź, czy zostały prawidłowo wykonane czynności opisane w pliku README biblioteki i czy podczas wykonywania tych instrukcji nie pojawiły się żadne błędy.

Jeśli nadal masz problemy z używaniem bibliotek dekodowania, sprawdź, czy w narzędziu do śledzenia problemów Media3 znajdują się najnowsze problemy. Jeśli chcesz zgłosić nowy problem, który dotyczy tworzenia natywnej części biblioteki, podaj pełne dane wyjściowe wiersza poleceń podczas uruchamiania instrukcji README. Pomoże nam to zdiagnozować problem.

Czy mogę odtwarzać filmy z YouTube bezpośrednio przy użyciu ExoPlayer?

Nie. ExoPlayer nie może odtwarzać filmów z YouTube, np. adresów URL w postaci https://www.youtube.com/watch?v=.... Zamiast tego należy korzystać z interfejsu YouTube IFrame Player API, który jest oficjalnym sposobem odtwarzania filmów z YouTube na urządzeniach z Androidem.

Odtwarzanie filmu się zacina

Urządzenie może nie być w stanie zdekodować treści wystarczająco szybko, jeśli np. szybkość transmisji lub rozdzielczość treści wykraczają poza możliwości urządzenia. Aby uzyskać dobrą wydajność na takich urządzeniach, być może trzeba będzie używać treści o niższej jakości.

Jeśli występują zacinanie się filmów na urządzeniu z Androidem w wersji od 6.0 (poziom interfejsu API 23) do 11 (poziom interfejsu API 30) włącznie, szczególnie podczas odtwarzania treści chronionych DRM lub z dużą liczbą klatek, spróbuj włączyć asynchroniczne kolejkowanie buforowania.