IOS Take some screenshots

I have an NSURL that contains a video, and I want to record a frame of this video ten times in a few seconds. And I have a code that will capture the image of my player, but I have a problem setting it up to capture 10 frames per second. I'm trying something like this, but it returns the same starting frame of the video, how many times? Here is what I have:

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

But instead of getting the frame at the current time I am video, I just get the starting frame?

How can I get a video frame 10 times per second?

Thanks for the help:)

+7
ios xcode video camera
Apr 03 '15 at 2:34
source share
2 answers

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; } 
+10
Apr 14 '15 at 5:55
source share

With CMTimeMake(A, B) you store a rational number, an exact fraction of A / B seconds, and the first parameter of this function takes an int value. Within 20 seconds of the video, you will capture a frame with the time ((int) 19.9) / 10 = 1.9 seconds in the last iteration of your loop. Use the CMTimeMakeWithSeconds(i, NSEC_PER_SEC) function to fix this problem.

+2
Apr 14 '15 at 5:03
source share



All Articles