You get the initial frame because you are trying to create a CMTime using the float value:
CMTime time = CMTimeMake(i, 10);
Since the CMTimeMake function takes int64_t as the first parameter, your float will be rounded to int and you will get the wrong result.
Allows you to slightly modify the code:
1) . First you need to find the total number of frames to get from the video. You wrote that you need 10 frames per second, so the code will be:
int requiredFramesCount = seconds * 10;
2) Next, you need to find a value that will increase your CMTime value at each step:
int64_t step = vidLength.value / requiredFramesCount;
3) And finally, you need to set requestTimeToleranceBefore and requestTimeToleranceAfter to kCMTimeZero to get the frame at the exact time:
imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
Here is what your code looks like:
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; }
Vladimir K Apr 14 '15 at 5:55 2015-04-14 05:55
source share