Uwaga na poniższe pytanie: Wszystkie zasoby są lokalne na urządzeniu - nie odbywa się strumieniowe przesyłanie strumieniowe w sieci. Filmy zawierają ścieżki dźwiękowe.
Pracuję nad aplikacją na iOS, która wymaga odtwarzania plików wideo z minimalnym opóźnieniem, aby rozpocząć dany klip wideo. Niestety nie wiemy, jaki konkretny klip wideo jest następny, dopóki nie musimy go faktycznie uruchomić. W szczególności: gdy odtwarzany jest jeden klip wideo, będziemy wiedzieć, jaki jest następny zestaw (w przybliżeniu) 10 klipów wideo, ale nie wiemy dokładnie, który z nich jest dokładnie, dopóki nie nadejdzie czas, aby „natychmiast” odtworzyć następny klip.
Aby spojrzeć na rzeczywiste opóźnienia rozpoczęcia, zadzwoniłem addBoundaryTimeObserverForTimes
do odtwarzacza wideo z okresem jednej milisekundy, aby zobaczyć, kiedy wideo faktycznie zaczęło się odtwarzać, i biorę różnicę tego znacznika czasu z pierwszym miejscem w kod wskazujący, który zasób rozpocząć odtwarzanie.
Z tego, co widziałem do tej pory, stwierdziłem, że użycie kombinacji AVAsset
wczytywania, a następnie tworzenia AVPlayerItem
z tego, gdy jest gotowy, a następnie czekania AVPlayerStatusReadyToPlay
przed wywołaniem gry, zwykle zajmuje od 1 do 3 sekund, aby rozpocząć spinacz.
Od tego czasu przeszedłem na to, co uważam za mniej więcej równoważne: dzwonienie [AVPlayerItem playerItemWithURL:]
i czekanie na AVPlayerItemStatusReadyToPlay
grę. Mniej więcej taka sama wydajność.
Jedną z rzeczy, które obserwuję, jest to, że ładowanie pierwszego elementu AVPlayera jest wolniejsze niż pozostałe. Wydaje się, że jednym z pomysłów jest wykonanie przed lotem AVPlayera z krótkim / pustym zasobem przed próbą odtworzenia pierwszego wideo, co może być dobrą praktyką ogólną. [ Powolny start dla AVAudioPlayer przy pierwszym odtwarzaniu dźwięku
Bardzo chciałbym skrócić czas rozpoczęcia filmu tak bardzo, jak to możliwe i mam kilka pomysłów na eksperymenty, ale chciałbym uzyskać wskazówki od każdego, kto mógłby pomóc.
Aktualizacja: idea 7, poniżej, w stanie zaimplementowanym, daje czasy przełączania około 500 ms. To jest poprawa, ale byłoby miło zrobić to jeszcze szybciej.
Pomysł 1: Użyj N AVPlayers (nie zadziała)
Używając ~ 10 AVPPlayer
obiektów i uruchamiaj i zatrzymuj wszystkie ~ 10 klipów, a kiedy już wiemy, który z nich naprawdę potrzebujemy, przełącz się na poprawny i wznów pauzę AVPlayer
i zacznij wszystko od nowa w następnym cyklu.
Nie sądzę, żeby to działało, ponieważ przeczytałem, że AVPlayer's
w iOS jest mniej więcej limit 4 aktywnych . Ktoś pytał o to tutaj na StackOverflow i dowiedział się o limicie 4 AVPlayer: szybkie przełączanie między filmami przy użyciu avfoundation
Pomysł 2: Użyj AVQueuePlayer (nie zadziała)
Nie wierzę, że wrzucenie 10 AVPlayerItems
do AVQueuePlayer
i załadowałoby je wszystkie dla płynnego startu. AVQueuePlayer
jest kolejką i myślę, że tak naprawdę tylko sprawia, że następny film w kolejce jest gotowy do natychmiastowego odtwarzania. Nie wiem, który z ~ 10 filmów chcemy odtworzyć, dopóki nie nadejdzie czas, aby to rozpocząć. ios-avplayer-video-preloading
Pomysł 3: Załaduj, odtwarzaj i zachowaj AVPlayerItems
w tle (jeszcze nie w 100% - ale nie wygląda dobrze)
Sprawdzam, czy ładowanie i odtwarzanie pierwszej sekundy każdego klipu wideo w tle (wyłączanie wyjścia wideo i audio) przynosi jakiekolwiek korzyści i zachowuje odniesienie do każdego z nich AVPlayerItem
oraz kiedy wiemy, który element należy odtworzyć real, zamień ten jeden i zamień działający w tle AVPlayer z aktywnym. Wypłukać i powtórzyć.
Teoria byłaby taka, że ostatnio odtwarzane AVPlayer/AVPlayerItem
utwory mogą nadal zawierać pewne przygotowane zasoby, które przyspieszyłyby późniejsze odtwarzanie. Jak dotąd nie widziałem korzyści z tego, ale być może nie mam AVPlayerLayer
poprawnej konfiguracji dla tła. Wątpię, czy to naprawdę poprawi sytuację w porównaniu z tym, co widziałem.
Pomysł 4: Użyj innego formatu pliku - może takiego, który jest szybszy do załadowania?
Obecnie używam formatu .m4v (video-MPEG4) H.264. H.264 ma wiele różnych opcji kodeków, więc możliwe jest, że niektóre opcje będą szybciej wyszukiwane niż inne. Zauważyłem, że użycie bardziej zaawansowanych ustawień, które zmniejszają rozmiar pliku, wydłuża czas wyszukiwania, ale nie znalazłem żadnych opcji, które idą w drugą stronę.
Pomysł 5: Połączenie bezstratnego formatu wideo + AVQueuePlayer
Jeśli istnieje format wideo, który szybko się ładuje, ale być może tam, gdzie rozmiar pliku jest szalony, jednym z pomysłów może być wstępne przygotowanie pierwszych 10 sekund każdego klipu wideo z wersją, która jest rozdęta, ale szybsza do załadowania, ale z powrotem to wszystko z zasobem zakodowanym w H.264. Użyj odtwarzacza AVQueuePlayer i dodaj pierwsze 10 sekund w nieskompresowanym formacie pliku, a następnie w formacie H.264, który uzyskuje do 10 sekund czasu przygotowania / wstępnego ładowania. Dostałbym więc „to, co najlepsze” z obu światów: szybki czas uruchamiania, ale także korzyści wynikające z bardziej kompaktowego formatu.
Pomysł 6: Użyj niestandardowego odtwarzacza AVPlayer / napisz własny / użyj cudzego
Biorąc pod uwagę moje potrzeby, być może nie mogę korzystać z AVPlayera, ale muszę uciekać się do AVAssetReader i dekodować pierwsze kilka sekund (ewentualnie zapisać plik raw na dysk), a jeśli chodzi o odtwarzanie, użyć formatu raw do jego odtworzenia z powrotem szybko. Wydaje mi się, że jest to ogromny projekt, a jeśli podejdę do tego naiwnie, to jest niejasne / mało prawdopodobne, żebym nawet lepiej działał. Każda zdekodowana i nieskompresowana klatka wideo zajmuje 2,25 MB. Mówiąc naiwnie - jeśli zdecydujemy się na ~ 30 fps dla wideo, skończymy z wymaganiem odczytu z dysku ~ 60 MB / s, co prawdopodobnie jest niemożliwe / pchanie go. Oczywiście musielibyśmy zastosować pewien poziom kompresji obrazu (być może natywne formaty kompresji openGL / es przez PVRTC) ... ale to trochę szalone. Może jest tam biblioteka, z której mogę skorzystać?
Pomysł 7: Połącz wszystko w jeden zasób filmu i seekToTime
Jednym z pomysłów, który może być łatwiejszy niż niektóre z powyższych, jest połączenie wszystkiego w jeden film i użycie seekToTime. Chodzi o to, że skakalibyśmy po całym miejscu. Zasadniczo swobodny dostęp do filmu. Myślę, że to może naprawdę działać dobrze: avplayer-movie-playing-lag-in-ios5
Jak myślisz, które podejście byłoby najlepsze? Jak dotąd nie poczyniłem tak dużych postępów w zakresie zmniejszania opóźnienia.