2015-04-03 14 views
7

Ho un NSURL che contiene un video e voglio registrare un fotogramma di quel video dieci volte ogni secondo. E ho il codice che catturerà un'immagine del mio lettore, ma ho difficoltà a configurarlo per catturare 10 fotogrammi al secondo. Sto provando qualcosa del genere, ma sta restituendo lo stesso frame iniziale del video, il numero corretto di volte? Ecco cosa ho:iOS scatta più scatti dello schermo

AVAsset *asset = [AVAsset assetWithURL:videoUrl]; 
CMTime vidLength = asset.duration; 
float seconds = CMTimeGetSeconds(vidLength); 
int frameCount = 0; 
for (float i = 0; i < seconds;) { 
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset]; 
    CMTime time = CMTimeMake(i, 10); 
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL]; 
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef]; 
           CGImageRelease(imageRef); 
NSString* filename = [NSString stringWithFormat:@"Documents/frame_%d.png", frameCount]; 
NSString* pngPath = [NSHomeDirectory() stringByAppendingPathComponent:filename]; 

[UIImagePNGRepresentation(thumbnail) writeToFile: pngPath atomically: YES]; 
frameCount++; 
i = i + 0.1; 
} 

Ma invece di ottenere il fotogramma al momento attuale del video, ho appena ottenuto il frame iniziale?

Come posso ottenere il frame del video 10 volte al secondo?

Grazie per l'aiuto :)

risposta

2

Con CMTimeMake(A, B) si memorizza un numero razionale, una frazione di secondi esatti A/B, e il primo parametro di questa funzione prende il valore int. Per 20 secondi di video acquisirai un fotogramma con tempo ((int) 19.9)/10 = 1.9 secondo nell'ultima iterazione del tuo ciclo. Utilizzare la funzione CMTimeMakeWithSeconds(i, NSEC_PER_SEC) per risolvere questo problema di orario.

10

Hai trovato fotogramma iniziale, perché si sta cercando di creare CMTime con l'aiuto del valore decimale:

CMTime time = CMTimeMake(i, 10); 

Dal CMTimeMake funzione prende int64_t valore come primo parametro, il valore del float sarà arrotondato a int, e otterrai risultati errati.

Lets modificare il codice un po ':

1) In un primo momento, è necessario trovare contare frames totali che è necessario per ottenere dal video. Hai scritto che avete bisogno di 10 fotogrammi al secondo, in modo che il codice sarà:

int requiredFramesCount = seconds * 10; 

2) Dopodiché è necessario trovare un valore che sarà aumentare il tuo valore CMTime ad ogni passo:

int64_t step = vidLength.value/requiredFramesCount; 

3) e, infine, è necessario impostare requestedTimeToleranceBefore e requestedTimeToleranceAfter a kCMTimeZero, per ottenere un fotogramma alla volta preciso:

imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 
imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 

Ecco come il codice sarà simile:

CMTime vidLength = asset.duration; 
float seconds = CMTimeGetSeconds(vidLength); 

int requiredFramesCount = seconds * 10; 
int64_t step = vidLength.value/requiredFramesCount; 

int value = 0; 

for (int i = 0; i < requiredFramesCount; i++) { 

    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset]; 
    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 
    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 

    CMTime time = CMTimeMake(value, vidLength.timescale); 

    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL]; 
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef); 
    NSString* filename = [NSString stringWithFormat:@"Documents/frame_%d.png", i]; 
    NSString* pngPath = [NSHomeDirectory() stringByAppendingPathComponent:filename]; 

    [UIImagePNGRepresentation(thumbnail) writeToFile: pngPath atomically: YES]; 

    value += step; 
} 
+0

La stessa domanda utilizzando Swift http://stackoverflow.com/questions/32286320/grab-frames-from-video-using-swift/32297251 – arpo

Problemi correlati