0

I am trying to fetch all frames of video and converting and storing them as individual images. I am using this code in AV Foundation Programming Guide.

the code for getting multiple images is

CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 600);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 600);
CMTime end = CMTimeMakeWithSeconds(durationSeconds, 600);

this is hard coded, but I want to convert whole video. I know I can use for loop but what to do with this durationsecond means how can I use from begging to end to get all frames?

here is my attempt

for(float f=0.0; f<=durationSeconds; f++) {
        [times addObject:[NSValue valueWithCMTime:CMTimeMakeWithSeconds(durationSeconds, 600)]];
}
S.J
  • 3,063
  • 3
  • 33
  • 66

1 Answers1

1

Any time you're about to write hundreds of lines of nearly identical code is probably a time where you need to be using a loop of some sort:

for (int currentFrame = 0; currentFrame < durationSeconds; ++currentFrame) {
    CMTime currentTime = CMTimeMakeWithSeconds(i, 600);
    // the rest of the code you need to create the image or whatever
}

That snippet will grab one frame per second. If you wanted to grab 30 frames per second, it'd look more like this:

const CGFloat framesPerSecond = 30.0;

for (int currentFrame = 0; currentFrame < (durationSeconds * framesPerSecond); ++currentFrame) {
    CMTime currentTime = CMTimeMakeWithSeconds(currentFrame/framesPerSecond, 600);
    // again, the code you need to create the image from this time
}

Just set the value of framesPerSecond to however many frames per second you want to capture.


As a disclaimer, I'm not completely familiar with this stuff, so a <= might be appropriate in the conditional statements here.


ADDENDUM: The code I've posted is only going to grab the timestamp for which to grab an image. The rest of the code should look something like this:

AVAsset *myAsset = // your asset here
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];

NSError *error;
CMTime actualTime;

CGImageRef currentImage = [imageGenerator copyCGImageAtTime:currentTime 
                                                 actualTime:&actualTime 
                                                      error:&error];

if (!error) {
    [someMutableArray addObject:[[UIImage alloc] initWithCGImage:currentImage]];
}
nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • I was successfully looping, generating images and saving images in storage, the only thing I was stuck in manipulating durationsecond form begging to end. Is there any way to find frame rate of an video? to precisly get all frames. – S.J Jul 06 '14 at 02:47
  • I don't know, and I'm not sure it could be determined accurately. The rate it was recorded in and the rate it displays in could be different. You just need to decide on a quality you want to capture frames at. – nhgrif Jul 06 '14 at 02:49
  • like iPhone 5s slow motion feature make video of 120 frame per second. – S.J Jul 06 '14 at 02:50
  • It captures video at 120 frames per second. It doesn't play back the video at 120 frames per second. If it played back the video at the same rate it captured it at, it wouldn't be slow motion, would it? – nhgrif Jul 06 '14 at 02:51
  • the code has little problem I nslog the currentFrame/framesPerSecond, I am getting the repeated number from 0 to 6 means actually only 6 frames are original rest are repeated of 0, 1, 2... – S.J Jul 06 '14 at 14:17
  • Try: `((CGFloat)currentFrame/framesPerSecond)`. It's probably doing integer division. – nhgrif Jul 06 '14 at 14:19
  • Please view the question portion I have updated it with NSLogs the repeated pattern I am getting. – S.J Jul 06 '14 at 15:48
  • It would be more helpful if you actually included the code you're using, including how you're getting the values to log. – nhgrif Jul 06 '14 at 15:49
  • I have included all of the code, I am not just viewing the log but also viewing the generated images and images are also repeating. – S.J Jul 06 '14 at 15:57
  • Change `framesPerSecond` from an `int` to a `CGFloat` for starters, see if that helps. – nhgrif Jul 06 '14 at 15:58
  • initial framepersecond variable is 0 but in next line I am getting the video frame rate and assigning to framepersecond variable, I also tried converting framepersecond variable to cgfloat but still repeating issue exist. – S.J Jul 06 '14 at 16:03
  • Its not working. Still getting repeated issue in log and in generated images. – S.J Jul 06 '14 at 16:14
  • I don't know what to tell you. I don't know enough about this code to help you further. Truly, you should edit the question back to its original form and post the existing problem as a new question. – nhgrif Jul 06 '14 at 16:15
  • Thank you so very very much for the replies and help. Really its a big big help from you. – S.J Jul 06 '14 at 16:20
  • @S.J hey there, I working on the same problem, as you did you find a fix or solution? – iqueqiorio Apr 11 '15 at 21:56