I\'m currently extracting every frame from a video with AVAssetImageGenerator
, but sometimes it returns me successively 2 times almost the same image (they do not h
I was using a slightly different way for calculating the CMTime request, and it seemed to work. Here is the code (assuming iOS) :
-(void)extractImagesFromMovie {
// set the asset
NSString* path = [[NSBundle mainBundle] pathForResource:@"myMovie" ofType:@"MOV"];
NSURL* movURL = [NSURL fileURLWithPath:path];
NSMutableDictionary* myDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES] ,
AVURLAssetPreferPreciseDurationAndTimingKey ,
[NSNumber numberWithInt:0],
AVURLAssetReferenceRestrictionsKey, nil];
AVURLAsset* movie = [[AVURLAsset alloc] initWithURL:movURL options:myDict];
// set the generator
AVAssetImageGenerator* generator = [[AVAssetImageGenerator assetImageGeneratorWithAsset:movie] retain];
generator.requestedTimeToleranceBefore = kCMTimeZero;
generator.requestedTimeToleranceAfter = kCMTimeZero;
// look for the video track
AVAssetTrack* videoTrack;
bool foundTrack = NO;
for (AVAssetTrack* track in movie.tracks) {
if ([track.mediaType isEqualToString:@"vide"]) {
if (foundTrack) {NSLog (@"Error - - - more than one video tracks"); return(-1);}
else {
videoTrack = track;
foundTrack = YES;
}
}
}
if (foundTrack == NO) {NSLog (@"Error - - No Video Tracks at all"); return(-1);}
// set the number of frames in the movie
int frameRate = videoTrack.nominalFrameRate;
float value = movie.duration.value;
float timeScale = movie.duration.timescale;
float totalSeconds = value / timeScale;
int totalFrames = totalSeconds * frameRate;
NSLog (@"total frames %d", totalFrames);
int timeValuePerFrame = movie.duration.timescale / frameRate;
NSMutableArray* allFrames = [[NSMutableArray new] retain];
// get each frame
for (int k=0; k< totalFrames; k++) {
int timeValue = timeValuePerFrame * k;
CMTime frameTime;
frameTime.value = timeValue;
frameTime.timescale = movie.duration.timescale;
frameTime.flags = movie.duration.flags;
frameTime.epoch = movie.duration.epoch;
CMTime gotTime;
CGImageRef myRef = [generator copyCGImageAtTime:frameTime actualTime:&gotTime error:nil];
[allFrames addObject:[UIImage imageWithCGImage:myRef]];
if (gotTime.value != frameTime.value) NSLog (@"requested %lld got %lld for k %d", frameTime.value, gotTime.value, k)
}
NSLog (@"got %d images in the array", [allFrames count]);
// do something with images here...
}