2015-04-03 30 views
7

Ich habe eine NSURL, die ein Video enthält, und ich möchte ein Bild von diesem Video zehn Mal pro Sekunde aufnehmen. Und ich habe Code, der ein Bild von meinem Player aufnehmen wird, aber ich habe Probleme beim Einrichten von 10 Bildern pro Sekunde. Ich versuche so etwas, aber es gibt den gleichen Anfangsrahmen des Videos, die richtige Anzahl von Malen? Hier ist was ich habe:iOS Take mehrere Screenshots

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

Aber anstatt den Rahmen zur aktuellen Zeit i des Videos zu bekommen, bekomme ich nur den ursprünglichen Rahmen?

Wie bekomme ich den Rahmen des Videos 10 Mal pro Sekunde?

Danke für die Hilfe :)

Antwort

2

Mit CMTimeMake(A, B) speichern Sie eine rationale Zahl, eine genaue Fraktion A/B Sekunden und erste Parameter dieser Funktion int Wert annimmt. Für 20 Sekunden Video werden Sie ein Bild mit der Zeit ((int) 19,9)/10 = 1,9 Sekunden in der letzten Iteration Ihres Zyklus erfassen. Verwenden Sie die CMTimeMakeWithSeconds(i, NSEC_PER_SEC) Funktion, um dieses Zeitproblem zu beheben.

10

Sie erhalten Anfangsrahmen, weil Sie versuchen, cmtime mit Hilfe von Float-Wert zu erstellen:

CMTime time = CMTimeMake(i, 10); 

Da CMTimeMake Funktion int64_t Wert als erster Parameter wird Ihr Float-Wert gerundet werden braucht int, und Sie erhalten ein falsches Ergebnis.

Hier können Sie Ihren Code ein wenig ändern:

1) Zunächst müssen Sie insgesamt Frames zählen finden, dass Sie aus dem Video erhalten müssen. Sie schrieben, dass Sie 10 Frames pro Sekunde benötigen, so wird der Code sein:

int requiredFramesCount = seconds * 10; 

2) Weiter Sie einen Wert finden müssen, die auf jedem Schritt Ihres cmtime Wert zuzunehmen:

int64_t step = vidLength.value/requiredFramesCount; 

3) und schließlich müssen Sie requestedTimeToleranceBefore und requestedTimeToleranceAfter zu kCMTimeZero, setzen einen Rahmen zu genauen Zeitpunkt zu bekommen:

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

Hier ist, wie Ihr Code aussehen wird:

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

Die gleiche Frage mit Swift http://stackoverflow.com/questions/32286320/grab-frames-from-video-using-swift/32297251 – arpo