2012-02-15 13 views
11

Sto cercando di creare le miniature per i file video:È possibile far funzionare AVURLAsset senza un'estensione di file?

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

Il problema è che i file video vengono memorizzati in un content-addressable store e non hanno le estensioni. Questo sembra gettare AVURLAsset fuori, come l'asset viene creato, ma dopo aver letto l'immagine del fotogramma ottengo il seguente errore:

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} 

È questo il documentato o citato da qualche parte? Non posso credere di essere davvero costretto a passare le informazioni sul formato del file attraverso il nome del file. L'argomento options per l'inizializzatore AVURLAsset sembra un buon posto per fornire il tipo di file, ma secondo la documentazione non sembra esserci alcun supporto per questo.

PS. Ho testato il codice, lo stesso file con l'estensione corretta produce le miniature bene.

risposta

10

Alla fine creo temporaneamente un collegamento fisico al file e fornisco l'estensione corretta al collegamento fisico. È un trucco, mi piacerebbe vedere una soluzione migliore. Ho submitted a bug report contro AVURLAsset, si spera che Apple potrebbe aggiungere la funzione per leggere le informazioni sul formato del file dal dizionario options.

+0

Mi puoi dire? in che modo hai creato l'hard link al file, in realtà ho un tuo video url e devo creare l'anteprima di quel video usando il suo URL –

+0

Intendi un URL di file locale o un normale URL HTTP di YouTube? Un URL di file locale può essere facilmente collegato tramite '[NSFileManager linkItemAtURL: toURL: error:]'. La creazione di una miniatura da un URL video di YouTube HTTP è degna di una [domanda separata] (http://stackoverflow.com/questions/ask), IMHO. – zoul

+1

Ancora non è fissato in iOS7 e '[[AVAudioPlayer alloc] initWithContentsOfURL: Errore url: nil];' non ha alcun problema con i file non avendo estensioni –

3

risposta 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) 

risposta 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]; 

E ora AVURLAsset funziona con tmpPath.

+0

Hey .. lo stesso approccio funziona in caso di PHAsset .. Ero in grado di leggere un file locale da path prelevato da PHAsset.quindi Linking funziona – ProblemSlover

4

Credo di aver trovato una soluzione alternativa in iOS7. Il trucco è usare AVAssetResourceLoader. Passare in AVURLAsset un URL fittizio che contiene uno schema creato dall'utente, che causerà la chiamata di AVAssetResourceLoaderDelegate ad es. 'myscheme: //random.com/file.mp4' Come puoi vedere con l'URL che ho creato, ha un'estensione .mp4, questo consentirà ad AVPlayer di aprire correttamente il file, purché segui il passo successivo correttamente .

ora implementare l'AVAssetResourceLoaderDelegate di utilizzare l'attuale cioè URL 'http://actual.com/file' I dati saranno ora passate correttamente fino alla AVPlayer senza lamentarsi di non essere in grado di aprire quel tipo di formato di file.

+1

Sto lavorando per implementare la soluzione alternativa consigliata e sto implementando AVAssetResourceLoaderDelegate, ma non riesco ancora a far riprodurre a AVPlayer la sorgente audio. Puoi approfondire cosa intendevi per "Ora implementare AVAssetResourceLoaderDelegate per utilizzare l'URL effettivo, ad esempio" http://actual.com/file ""? Stai scambiando gli URL in qualche modo? – Shackleford

+1

L'ho fatto qualche tempo fa, ma fondamentalmente ho usato uno schema di risorse con l'estensione .mp4 in modo che il delegato venisse chiamato e non saltato. Una volta all'interno di quel delegato ho usato l'indirizzo di risorsa reale per caricarlo, ho usato un metodo statico per ottenere l'indirizzo di risorsa reale invece di usare quello fittizio che era necessario per il delegato per essere chiamato correttamente. – Pellet