2012-02-15 17 views
11

Estoy tratando de crear imágenes en miniatura para archivos de vídeo:¿Es posible hacer que AVURLAsset funcione sin una extensión de archivo?

- (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; 
    } 
} 

El problema es que los archivos de vídeo se almacenan en un content-addressable store y no tienen extensiones. Esto parece tirar AVURLAsset fuera, como el activo se crea, pero la lectura de la imagen Marco me sale el siguiente error:

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} 

está documentado el mencionado o en alguna parte? No puedo creer que realmente me veo obligado a pasar la información del formato de archivo a través del nombre del archivo. El argumento options para el inicializador AVURLAsset parece un buen lugar para suministrar el tipo de archivo, pero según la documentación no parece haber soporte para eso.

PS. He probado el código, el mismo archivo con la extensión correcta produce las miniaturas muy bien.

Respuesta

10

Al final creo temporalmente un enlace fijo al archivo y le doy la extensión correcta al enlace permanente. Aunque es un truco, me gustaría ver una mejor solución. Tengo submitted a bug report contra AVURLAsset, con suerte Apple podría agregar la característica para leer la información de formato de archivo del diccionario options.

+0

¿Puede decirme por favor? que cómo creó el enlace al archivo, en realidad tengo una url de video you tube y tengo que crear la miniatura de ese video usando su url –

+0

¿Quiere decir una URL de archivo local, o una URL de HTTP HTTP regular? Una URL de archivo local se puede enlazar fácilmente usando '[NSFileManager linkItemAtURL: toURL: error:]'. Crear una miniatura desde una URL de video de YouTube HTTP es digna de una [pregunta separada] (http://stackoverflow.com/questions/ask), en mi humilde opinión. – zoul

+1

Aún no se ha solucionado en iOS7 y '[[AVAudioPlayer alloc] initWithContentsOfURL: url error: nil];' no tiene problema con los archivos que no tienen extensiones –

3

respuesta Swift:

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) 

La respuesta completa 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]; 

Y ahora AVURLAsset trabajará con tmpPath.

+0

Oye ... el mismo enfoque funciona en el caso de PHAsset .. No pude leer un archivo local por ruta de PHAsset.así que Linking funciona – ProblemSlover

4

Creo que he encontrado una solución en iOS7. El truco es usar un AVAssetResourceLoader. Pase al AVURLAsset una URL ficticia que contiene un esquema creado por usted, que hará que se llame a AVAssetResourceLoaderDelegate p. Ej. 'myscheme: //random.com/file.mp4' Como puede ver con la URL que creé, tiene una extensión .mp4, esto permitirá que AVPlayer abra correctamente el archivo, siempre y cuando siga correctamente el siguiente paso .

Ahora aplicar la AVAssetResourceLoaderDelegate utilizar el ejemplo real de la URL 'http://actual.com/file' Los datos serán ahora pasan correctamente a través de la AVPlayer sin que se quejan de no poder abrir ese tipo de formato de archivo.

+1

Estoy trabajando para implementar su solución alternativa recomendada, y estoy implementando AVAssetResourceLoaderDelegate, pero aún no puedo hacer que AVPlayer reproduzca la fuente de audio. ¿Puede explicar lo que quiere decir con "Ahora implemente el AVAssetResourceLoaderDelegate para usar la URL real, es decir, 'http://actual.com/file'"? ¿Está intercambiando las URL de alguna manera? – Shackleford

+1

Hice esto hace un tiempo, pero básicamente utilicé un esquema de recursos con la extensión .mp4 para que el delegado se llamara y no se saltara. Una vez dentro de ese delegado, utilicé la dirección del recurso real para cargarlo, utilicé un método estático para obtener la dirección del recurso real en lugar de usar el objeto ficticio que se necesitaba para que el delegado se llamara correctamente. – Pellet

Cuestiones relacionadas