AVFoundation, похоже, не делает различий между локальными и нелокальными файлами, как между типом KIND используемых файлов или протоколов.Существует ОЧЕНЬ четкое различие между использованием mp4 / mov по сравнению с использованием потокового протокола HTTP Live через m3u8, но различия, использующие локальный или удаленный mp4, немного более размыты.
Чтобы расширить вышесказанное:
a) Если ваш «удаленный» актив - это M3U8 (то есть вы используете потоковую передачу по HTTP), то у вас нет никаких шансов.Неважно, находится ли M3U8 в вашей локальной файловой системе или на удаленном сервере, по множеству причин AVAssetReader и все функции, связанные с AVAsset, просто НЕ работают.However, AVPlayer, AVPlayerItem etc would work just fine.
b) Если это MP4 / MOV, необходимо провести небольшое расследование.Local MP4/MOV's work flawlessly.
Хотя в случае удаленных MP4 / MOV я могу создать (или извлечь из AVPlayerItem, AVPlayer или AVAssetTracks) AVURLAsset, с помощью которого я иногда могу успешно инициализировать AVAssetReader (я подробно остановлюсь на«иногда», в скором времени).ОДНАКО, copyNextSampleBuffer always returns nil in case of remote MP4's
.Поскольку некоторые вещи до момента вызова copyNextSampleBuffer работают, я не уверен на 100%, если:
i) copyNextSampleBuffer не работает для удаленных mp4, после того, как все остальные шаги были успешными,предполагаемая / ожидаемая функциональность.
ii) То, что «другие шаги», по-видимому, работают вообще для удаленных MP4, является случайностью реализации Apple, и эта несовместимость просто выходит на первый план, когда мы нажимаем copyNextSampleBuffer............. что это за "другие шаги", я подробно опишу в ближайшее время.
iii) Я делаю что-то не так, когда пытаюсь вызвать copyNextSampleBuffer для удаленных MP4.
Итак, @Paula, вы можете попытаться исследовать немного дальше с удаленными MOV / MP4.
Для справки, вот подходы, которые я пробовал для захвата кадра из видео:
a)
Создать AVURLAsset непосредственно из URL-адреса видео.
Извлечение видеодорожки с использованием [asset trackWithMediaType: AVMediaTypeVideo]
Подготовка AVAssetReaderTrackOutput с использованием видеодорожки в качестве источника.
Создайте AVAssetReader с помощью AVURLAsset.
Добавьте AVAssetReaderTrackOutput к AVAssetReader и начните чтение.
Извлечение изображений с помощью copyNextSampleBuffer.
b)
Создайте AVPlayerItem из URL-адреса видео, а затем AVPlayer из него (или создайте AVPlayerнепосредственно из URL).
Получите свойство 'актива' AVPlayer и загрузите его 'дорожки', используя «loadValuesAsynchronouslyForKeys:».
Разделите дорожки типа AVMediaTypeVideo (или просто вызовите trackWithMediaType: в активе после загрузки дорожек) и создайте AVAssetReaderTrackOutput с использованием видеодорожки.
Создание AVAssetReader с использованием 'актива', 'startReading' AVPlayer, а затем извлечение изображений с использованием copyNextSampleBuffer.
c)
Создание AVPlayerItem + AVPlayerили AVPlayer прямо с видео URL.
KVO для свойства AVPlayerItem «дорожки», и после загрузки дорожек отделяйте AVAssetTracks типа AVMediaTypeVideo.
Получить AVAsset из свойства 'asset' объекта AVPlayerItem / AVPlayer / AVAssetTrack.
Остальные шаги аналогичны подходу (b).
d)
Создайте AVPlayerItem + AVPlayer или AVPlayer непосредственно из URL-адреса видео.
KVO для свойства AVPlayerItem 'дорожки', и после загрузки дорожек отделяйте их от типа AVMediaTypeVideo.
Создайте AVMutableComposition и инициализируйте связанный AVMutableCompositionTrack типа AVMediaTypeVideo.
Вставьте соответствующий CMTimeRange из видео дорожки, полученной ранее, в этот AVMutableCompositionTrack.
Аналогично (b) и (c), теперь создайте свои AVAssetReader и AVAssetReaderTrackOutput, но с той разницей, что вы используете AVMutableComposition в качестве базового AVAsset для инициализации AVAssetReader и AVMutableCompositionTrack в качестве базового AVAssetTrack для вашего AVAssetputaderck,
'startReading' и использование copyNextSampleBuffer для получения кадров от AVAssetReader.
PS: я попробовал подход (d) здесь, чтобы обойти тот факт, что AVAsset, полученный непосредственно из AVPlayerItem или AVPlayer, не былсебя.Поэтому я хотел создать новый AVAsset из уже имеющихся у меня AVAssetTracks.По общему признанию хакерский, и, возможно, бессмысленный (где еще будет в конечном итоге информация о треке, если не исходный AVAsset!), Но это все равно стоило отчаянной попытки.
Вот сводка результатов для файлов различных типов:
1) Локальные MOV / MP4 - все 4 подхода работают безупречно.
2) Удаленные MOV / MP4 - актив и дорожки корректно извлекаются в подходах (b) - (d), и AVAssetReader также инициализируется, но copyNextSampleBuffer всегда возвращает nil.В случае (a) создание самого AVAssetReader завершается неудачно с NSOSStatusErrorDomain «Неизвестная ошибка» -12407.
3) Локальные M3U8 (доступ через внутренний / внутренний HTTP-сервер в приложении) - Подходы (a), (b) и (c) с треском провалились, так как попытка получить AVURLAsset / AVAsset в любой форме или форме для файлов, передаваемых через M3U8, является глупым поручением.
В случае (a) ресурс вообще не создается, и вызов initWithURL: на AVURLAsset завершается неудачно с «Неизвестной ошибкой» AVFoundationErrorDomain -11800.
В случае (b) и (c) получение AVURLAsset из AVPlayer / AVPlayerItem или AVAssetTracks возвращает объект SOME, но при обращении к свойству дорожек на нем всегда возвращается пустой массив.
В случае (d) я могу успешно извлекать и изолировать видеодорожки, но при попытке создать AVMutableCompositionTrack происходит сбой при попытке вставить CMTimeRange из исходной дорожки в AVMutableCompositionTrack,с «Неизвестной ошибкой» NSOSStatusErrorDomain -12780.
4) Удаленные M3U8 ведут себя точно так же, как локальные M3U8.
Я не совсем понимаю, почему этиразличия существуют или не могли быть смягчены Apple.Но вот, пожалуйста.