2013-02-12 31 views
11

Mamy aplikację, nad którą pracujemy, która wymaga odtwarzania plików wideo za pośrednictwem AVPlayer. Pliki muszą być przechowywane na urządzeniu użytkownika, ale także muszą być odtwarzane podczas pobierania.Pliki do pobrania AVPlayer i progresywnego wideo z AVURLAssets

W tym momencie zbudowaliśmy moduł pobierania, który korzysta z biblioteki ASIHTTPRequest, aby uzyskać pliki wideo za pośrednictwem PHP (nie chcemy, aby nośnik mógł być łączony za pośrednictwem publicznych adresów URL) i zapisywać je na dysku asynchronicznie.

Następnie ustawiliśmy AVPlayer zgodnie z AV Foundation Programming Guide, otrzymując plik z AVURLAsset, tworząc AVPlayerItem z zasobem, budując AVPlayer z elementem, a następnie ustawiając odtwarzacz na AVPlayerLayer. Odtwarzacz działa poprawnie z w pełni pobranym plikiem wideo i będzie również uruchamiał stopniowo pobierany plik o doskonałej jakości w symulatorze.

Niestety na prawdziwym urządzeniu zachowanie odtwarzacza ulega zmianie, gdzie zamiast tego wydaje się, że raz ładuje wideo i nie próbuje pobrać nowych pakietów z dysku. Powoduje to, że odtwarzacz odtwarza wideo i dźwięk aż do punktu w filmie, który wskazuje, gdzie postęp pobierania był w momencie załadowania zasobu (np. Jeśli 2 MB danych zostanie zbuforowane, to odtwarzacz zostanie utworzony, odtwarzacz będzie grał tylko do 2MB danych). Ponieważ ma nagłówek filmu, gracz z przyjemnością kontynuuje myślenie, że gra przez cały czas trwania filmu, ale żaden inny film nie jest wyświetlany na ekranie.

Ostatnia zmarszczka polega na tym, że jeśli wideo zostanie wstawione do AVComposition i AVPlayer zostanie utworzony z tym, progresywne wideo zagra dobrze. To byłoby dobre rozwiązanie (i jest to konieczne w przypadku naszej aplikacji), z tym że klient dla naszej aplikacji wymaga, aby wideo można było odtwarzać na Apple TV za pośrednictwem AirPlay, którego AVCompositions są niezdolne.

Czy ktoś wie, czy istnieje sposób na odtwarzanie progresywnego pobierania plików wideo przy użyciu odtwarzacza AVP zbudowanego z zestawu AVURLAssets? Czy istnieje sposób zmuszenia player/playerItem do odczytu z dysku przy pomocy zestawu AVURLA, tak jak wydaje się, że robi to z AVComposition, zamiast pozornego buforowania wideo w pamięci?

Dzięki!

+0

Czy kiedykolwiek pracowałeś nad tym problemem? Jaką wersję systemu iOS używasz i czy to zachowanie zmieniło się wraz z nowszymi wersjami? –

+0

Nie, nadal nie mam rozwiązania tego innego niż użycie AVComposition. W tym czasie używaliśmy iOS 5.1 i 6.0, a zachowanie nadal trwa przez 6.1. –

+0

@RobertNall Próbuję zrobić to samo, co z AVComposition - czy możesz nieco wyjaśnić, w jaki sposób wstawiłeś wideo do AVComposition? Jeśli odtwarzacz osiągnie EOF, odtwarzanie zostanie wznowione po pobraniu większej ilości danych? –

Odpowiedz

6

Nie mam rozwiązania, które sprawi, że będzie działać z AVURLAssets, ale używam nieco innego podejścia. Łączymy naszą aplikację z CocoaHTTPServer i odtwarzamy pliki wideo, które nie są w pełni pobrane przez żądanie HTTP na lokalny serwer.

Serwer zna całkowitą długość pliku i może zdecydować, patrząc na nagłówki HTTP, która część pliku jest żądana i albo ładuje je z dysku lub ze zdalnego źródła.

Podczas rozwijania tego zawsze pojawiają się 3 początkowe żądania, jedna dla pierwszych dwóch bajtów pliku, jedna z większych porcji od początku pliku i jedna porcja bezpośrednio z końca pliku. Dlatego zawsze trzeba było załadować przynajmniej ostatnią część bezpośrednio ze zdalnego serwera, ponieważ odtwarzacz byłby potrzebny od samego początku. Zgaduję, że to samo dzieje się z lokalnymi plikami, więc gracz wczytuje ostatnie bajty z pliku (które nie są prawymi ostatnimi bajtami) i nie będzie odtwarzany przez tę długość.

Będziesz musiał podklasę HTTPConnection i utworzyć własną klasę HTTPResponse, patrząc na dostarczoną "HTTPAsyncFileResponse".

Mam nadzieję, że dzięki temu dowiesz się, jak to osiągnąć, stosując inne podejście.

+0

Gdy otrzymasz odpowiedź zawierającą ostatni fragment pliku, czy piszesz puste bajty między początkiem i końcem, aby gracz miał końce bajtów we właściwym miejscu? –

+0

Zapisuję tylko na dysku, który pasuje do rzeczywistego rozmiaru pliku, więc fragmenty od początku będą zapisywane na dysku. Ale prośba do końca nie zostanie po prostu zwrócona graczowi. – Soph

+0

Myśląc o tym jeszcze raz, możesz również wypróbować coś takiego: http://aptogo.co.uk/2010/07/protecting-resources/, ale zamiast tego rzeczy kryptograficzne możesz zaimplementować odczyt/zapis ze zdalnego/lokalnego. – Soph