AVPlayer и прогрессивные загрузки видео с AVURLAssets

У нас есть приложение, над которым мы работаем, которое должно обеспечивать воспроизведение видеофайлов через AVPlayer. Файлы должны храниться на устройстве пользователя, но также должны воспроизводиться во время загрузки.

На данный момент мы создали модуль загрузки, который использует библиотеку ASIHTTPRequest для получения видеофайлов через PHP. (мы не хотим, чтобы носители могли быть связаны через общедоступные URL-адреса) и записывать их на диск асинхронно.

Затем мы настроили AVPlayer согласно Руководство по программированию AV Foundation, получение файла с AVURLAsset, создание AVPlayerItem с активом, создание AVPlayer с этим элементом, а затем установка проигрывателя на AVPlayerLayer . Плеер отлично работает с полностью загруженным видеофайлом, а также отлично запускает постепенно загружаемый файл в симуляторе.

К сожалению, на реальном устройстве поведение плеера меняется, вместо этого он, по-видимому, загружает видео один раз и не пытается захватить новые пакеты с диска. В результате проигрыватель будет воспроизводить видео и аудио до той точки в видео, которая отмечает, где прогресс загрузки был на момент загрузки ресурса (например, если 2 МБ данных буферизованы, то проигрыватель создается, игрок будет воспроизводить только до 2 МБ данных). Поскольку у него есть заголовок видео, игрок с радостью продолжит думать, что он воспроизводится на протяжении всего видео, но никакое другое видео не отображается на экран.

Последняя проблема заключается в том, что если видео вставлено в AVComposition и AVPlayer создан с его помощью, прогрессивное видео будет воспроизводиться нормально. Это было бы прекрасным решением (и в любом случае оно необходимо для нашего приложения), за исключением того, что клиент для нашего приложения требует, чтобы видео воспроизводилось на Apple TV через AirPlay, на что AVCompositions неспособны.

Кто-нибудь знает, есть ли способ воспроизводить постепенно загружаемые видеофайлы с помощью AVPlayer, созданного из AVURLAssets? Есть ли способ заставить player / playerItem читать с диска с помощью AVURLAsset так, как кажется делать с AVComposition вместо, казалось бы, кеширования видео в памяти?

Спасибо!


person Robert Nall    schedule 12.02.2013    source источник
comment
Вы когда-нибудь справлялись с этой проблемой? На какой версии iOS вы работали и изменилось ли это поведение с более поздними версиями?   -  person Chris Markle    schedule 02.08.2013
comment
Нет, у меня пока нет другого решения, кроме как использовать AVComposition. В то время мы использовали iOS 5.1 и 6.0, и поведение сохраняется до версии 6.1.   -  person Robert Nall    schedule 03.08.2013
comment
@RobertNall Я пытаюсь сделать то же самое с AVComposition - не могли бы вы рассказать немного, как именно вы вставили видео в AVComposition? Если проигрыватель достигает EOF, возобновляется ли воспроизведение после загрузки дополнительных данных?   -  person Jai Govindani    schedule 02.03.2014
comment
@Jai - Я не припомню подробностей, но я считаю, что мы просто сделали AVURLAsset из файла во время его загрузки, и AVComposition с радостью воспроизведет все, что там есть. Когда он достигнет конца уже загруженных данных, он оставит последний кадр, к которому у него был доступ, и продолжит воспроизведение, пока не достигнет длины (по времени) видео. Нам пришлось развернуть нашу собственную систему буферизации, пытаясь приблизительно оценить время, которое потребуется для загрузки всего видео, и приостановить воспроизведение, пока мы не почувствуем, что загрузка завершится раньше, чем воспроизведение.   -  person Robert Nall    schedule 04.03.2014
comment
(продолжение) Если проигрыватель действительно доходит до конца данных (но не до конца видео), он не будет автоматически приостанавливать / возобновлять воспроизведение. Однако, если вы обнаружите это и приостановите его вручную, вы можете возобновить проигрыватель после того, как будет загружено больше данных, и он будет воспроизводить только что загруженные данные. Надеюсь, это поможет!   -  person Robert Nall    schedule 04.03.2014
comment
@RobertNall спасибо, да, только что понял, что пока EOF ведет воспроизведение, все в порядке. Теперь мне просто нужно обнаружить EOF до того, как игрок попадет в него - дайте мне знать, если у вас есть какие-либо идеи о том, как это сделать, исследую и тоже посмотрю.   -  person Jai Govindani    schedule 04.03.2014
comment
@RobertNall Недавно я столкнулся с такой проблемой, я пытаюсь загрузить видео с помощью NSURLConnection и сохранить его в mp4 на диск. Воспроизведение видео во время загрузки. Первые несколько секунд работают нормально, но если проигрыватель воспроизводит видео до конца и еще не загрузил данные с сервера, проигрыватель останавливается и не возобновляет работу ... Решили ли вы эту проблему пока что? Вы можете поделиться своим решением? Спасибо   -  person Johnny    schedule 18.07.2014
comment
Извините, я не увидел комментарий вверху, вроде уже есть решение, попробую!   -  person Johnny    schedule 18.07.2014


Ответы (1)


У меня нет решения просто заставить его работать с AVURLAsset, но я использую немного другой подход. Мы связываем наше приложение с CocoaHTTPServer и воспроизводим видеофайлы, которые не были полностью загружены через HTTP-запрос к локальному серверу.

Сервер знает общую длину файла и может затем решить, просмотрев HTTP-заголовки, какая часть файла является запросом, и либо загрузить его с диска, либо из удаленного источника.

При его разработке всегда было 3 начальных запроса, один для первых двух байтов файла, один из большего фрагмента от начала файла и один фрагмент непосредственно из конца файла. Вот почему всегда нужно было загружать хотя бы последнюю часть напрямую с удаленного сервера, так как она нужна игроку с самого начала. Я предполагаю, что то же самое происходит с локальными файлами, поэтому игрок загружает последние байты из файла (которые не являются последними правыми байтами) и не будет воспроизводить эту длину.

Вам нужно будет создать подкласс HTTPConnection и создать свой собственный класс HTTPResponse, просмотрев предоставленный HTTPAsyncFileResponse.

Надеюсь, это дает вам представление о том, как добиться этого с помощью другого подхода.

person Soph    schedule 13.02.2013
comment
Когда вы получаете ответ, содержащий последний фрагмент файла, записываете ли вы пустые байты между началом и концом, чтобы у игрока были конечные байты в нужном месте? - person Robert Nall; 14.02.2013
comment
Я записываю на диск только то, что соответствует фактическому размеру файла, поэтому на диск будут записываться фрагменты с самого начала. Но запроса до конца не будет, он просто возвращается игроку. - person Soph; 14.02.2013
comment
Подумав об этом еще раз, вы также можете попробовать что-нибудь вроде этого: aptogo.co.uk/ 2010/07/security-resources, но вместо криптовалюты вы можете реализовать чтение / запись удаленно / локально. - person Soph; 22.02.2013
comment
Привет, Соф, даже если я не чувствую, что могу отметить это как полный ответ на вопрос, я все же хотел поблагодарить за то, что потратил время, чтобы предложить несколько предложений. Пока мы просто имеем дело с AVComposition и отказываемся от материала Airplay ... - person Robert Nall; 08.03.2013