Кэширование с помощью AVPlayer и AVAssetExportSession - PullRequest
9 голосов
/ 07 июня 2011

Я бы хотел кэшировать видео с прогрессивной загрузкой, используя AVPlayer. Как я могу сохранить элемент AVPlayer на диск? Я пытаюсь использовать AVAssetExportSession на currentItem игрока (который полностью загружен). Этот код дает мне « AVAssetExportSessionStatusFailed (операция не может быть завершена) »:

    AVAsset *mediaAsset = self.player.currentItem.asset;

    AVAssetExportSession *es = [[AVAssetExportSession alloc] initWithAsset:mediaAsset presetName:AVAssetExportPresetLowQuality];

    NSString *outPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.mp4"];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:outPath error:NULL];

    es.outputFileType = @"com.apple.quicktime-movie";
    es.outputURL = [[[NSURL alloc] initFileURLWithPath:outPath] autorelease];
    NSLog(@"exporting to %@",outPath);
    [es exportAsynchronouslyWithCompletionHandler:^{
        NSString *status = @"";

        if( es.status == AVAssetExportSessionStatusUnknown ) status = @"AVAssetExportSessionStatusUnknown";
        else if( es.status == AVAssetExportSessionStatusWaiting ) status = @"AVAssetExportSessionStatusWaiting";
        else if( es.status == AVAssetExportSessionStatusExporting ) status = @"AVAssetExportSessionStatusExporting";
        else if( es.status == AVAssetExportSessionStatusCompleted ) status = @"AVAssetExportSessionStatusCompleted";
        else if( es.status == AVAssetExportSessionStatusFailed ) status = @"AVAssetExportSessionStatusFailed";
        else if( es.status == AVAssetExportSessionStatusCancelled ) status = @"AVAssetExportSessionStatusCancelled";

        NSLog(@"done exporting to %@ status %d = %@ (%@)",outPath,es.status, status,[[es error] localizedDescription]);
    }];

Как я могу успешно экспортировать? Я пытаюсь скопировать mediaAsset в AVMutableComposition, но мне тоже не очень повезло.

Спасибо!

PS: Вот несколько вопросов от людей, пытающихся выполнить то же самое (но с помощью MPMoviePlayerController):

Ответы [ 2 ]

9 голосов
/ 13 июня 2011

Я пока не использую iOS 4.3 SDK, но мне было бы интересно узнать значение mediaAsset.exportable для 4.3, как описано здесь:

http://developer.apple.com/library/ios/#releasenotes/AudioVideo/RN-AVFoundation/_index.html#//apple_ref/doc/uid/TP40010717-CH1-SW4

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

Итак, я решил попробовать низкоуровневую инфраструктуру, поскольку в документации говорится, что вы можете подключить AVAssetReader и AVAssetWriter, чтобы получить тот же эффект, что и AVAssetExportSession, но с большим контролем. Однако следующий код:

NSError *readerError = nil;
AVAssetReader *reader = 
  [AVAssetReader assetReaderWithAsset:mediaAsset error:&readerError];
if (readerError) NSLog(@"Error instantiating asset reader: %@",
  [readerError localizedDescription]);

Дает следующий вывод:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of 
AVAssetReader with an asset at non-local URL 'http://example.com/test.mp3''

Обратите внимание, что я проверил это с рабочим URL, но заменил его на поддельный выше. Мне кажется, что iOS не поддерживает функциональность, которую мы ищем. Насколько я знаю, AVAssetExportSession использует AVAssetReader под капотом и просто сообщает о гораздо менее описательной ошибке при сбое. Было бы неплохо, если бы они просто документировали это. В документах для AVAssetExportSession ничего не говорится о том, что актив должен быть локальным:

http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAssetExportSession_Class/Reference/Reference.html#//apple_ref/occ/cl/AVAssetExportSession

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

0 голосов
/ 05 июля 2011

Конечно, это не работает на iOS 4.X. Кто-нибудь пытался заставить его работать на iOS 5 Beta?

Кажется, это отсутствующий плод. В документации нигде не указано, что он не поддерживает доступ к данным для сетевых носителей. Даже сообщения об ошибках и другие вещи в API выглядят странно и кажутся неполными при попытке его запустить. Скорее всего, это будет поддерживаться в ближайшее время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...