Возможно ли сделать работу AVURLAsset без расширения файла?

Я пытаюсь создать эскизы для видеофайлов:

- (UIImage*) thumbnailForVideoAtURL: (NSURL*) videoURL
{
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    CGImageRef imageHandle = [generator copyCGImageAtTime:kCMTimeZero actualTime:NULL error:NULL];
    if (imageHandle) {
        UIImage *frameImage = [UIImage imageWithCGImage:imageHandle];
        CFRelease(imageHandle);
        return frameImage;
    } else {
        return nil;
    }
}

Уловка заключается в том, что видеофайлы хранятся в контент-адресуемом хранилище и не имеют расширений. Похоже, что вы отбрасываете AVURLAsset, так как объект создается, но после считывания изображения кадра появляется следующая ошибка:

Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo=0x167170 {NSLocalizedFailureReason=This media format is not supported., NSUnderlyingError=0x163a00 "The operation couldn’t be completed. (OSStatus error -12847.)", NSLocalizedDescription=Cannot Open}

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

PS. Я протестировал код, тот же файл с правильным расширением создает миниатюры просто отлично.

Ответ 1

В конце концов я временно создаю жесткую ссылку на файл и даю правильное расширение для жесткой ссылки. Его взломать, хотя, Id нравится видеть лучшее решение. Ive отправил отчет об ошибке против AVURLAsset, надеюсь, Apple может добавить эту функцию, чтобы прочитать информацию о формате файла из словаря options.

Ответ 2

Я считаю, что нашел обходной путь в iOS7. Хитрость заключается в использовании AVAssetResourceLoader. Передайте в AVURLAsset фиктивный URL-адрес, который содержит созданную вами схему, которая вызовет вызов AVAssetResourceLoaderDelegate, например. 'Myscheme://random.com/file.mp4' Как вы можете видеть с URL-адресом, который я создал, он имеет расширение .mp4, это позволит AVPlayer правильно открыть файл, если вы выполните следующий шаг правильно.

Теперь реализуем AVAssetResourceLoaderDelegate, чтобы использовать фактический URL, т.е. http://actual.com/file ' Теперь данные будут правильно переданы в AVPlayer, не жалуясь на то, что они не смогут открыть формат этого типа.

Ответ 3

Быстрый ответ:

let filePath = ###YOU SET THIS###
let fileManager = NSFileManager.defaultManager()
let documentsURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .AllDomainsMask).last!
let tmpURL = documentsURL.URLByAppendingPathComponent("tmp.caf")
_ = try? fileManager.removeItemAtURL(tmpURL)
_ = try? fileManager.linkItemAtURL(fileURL, toURL: tmpURL)

Полный ответ Obj-C:

NSString *filePath = ###YOU SET THIS###
NSFileManager *dfm = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *tmpPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"tmp.caf"];
[dfm removeItemAtPath:tmpPath error:nil];
[dfm linkItemAtPath:filePath toPath:tmpPath error:nil];

И теперь AVURLAsset будет работать с tmpPath.