Search code examples
iosobjective-cavfoundationcmtime

Need assistance regarding CMTimeMakeWithSeconds


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

Solution

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