分享一个获取视频帧的代码(解决时间不准确问题)留给自己备忘

来源:互联网 发布:山东优化关键词公司 编辑:程序博客网 时间:2024/04/28 05:41
使用AVFoundation 获取一组视频的帧
- (IBAction)goCap:(id)sender {        NSBundle *mainBundle = [NSBundle mainBundle];    NSString *urlAsString = [mainBundle pathForResource:@"asdf"                                                 ofType:@"mp4"];    NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]                                                     forKey:AVURLAssetPreferPreciseDurationAndTimingKey];    NSURL    *url = [NSURL fileURLWithPath:urlAsString];        AVURLAsset *myAsset = [[AVURLAsset alloc] initWithURL:url options:opts];            float minute = 0.0f, second = 0.0f; //    value为  总帧数,timescale为  fps    second = myAsset.duration.value / myAsset.duration.timescale; // 获取视频总时长,单位秒        self.myImageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];        self.myImageGenerator.appliesPreferredTrackTransform = YES;//解决 时间不准确问题    self.myImageGenerator.requestedTimeToleranceBefore = kCMTimeZero;    self.myImageGenerator.requestedTimeToleranceAfter = kCMTimeZero;            // 获取视频总时长,单位秒    Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);        NSLog(@"%f~!~!~!~",durationSeconds);    CMTime firstThird = CMTimeMakeWithSeconds(10.0, 600);    CMTime secondThird = CMTimeMakeWithSeconds(11.0, 600);    CMTime end = CMTimeMakeWithSeconds(12.0, 600);    NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird],[NSValue valueWithCMTime:end],nil];      //    myImageGenertor  必须为strong    [self.myImageGenerator generateCGImagesAsynchronouslyForTimes:times                                         completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime,                                                             AVAssetImageGeneratorResult result, NSError *error) {                                                                                          NSString *requestedTimeString = (NSString *)                                             CFBridgingRelease(CMTimeCopyDescription(NULL, requestedTime));                                             NSString *actualTimeString = (NSString *)                                             CFBridgingRelease(CMTimeCopyDescription(NULL, actualTime));                                             NSLog(@"Requested: %@; actual %@", requestedTimeString, actualTimeString);                                                                                          if (result == AVAssetImageGeneratorSucceeded) {                                                 // Do something interesting with the image.                                                 NSLog(@"asdfasdgtryer4563464");                                                                                                  UIImage* image1 = [UIImage imageWithCGImage: image];//                                                  UIImageWriteToSavedPhotosAlbum(image1, self, nil, nil);                                             }                                                                                          if (result == AVAssetImageGeneratorFailed) {                                                 NSLog(@"Failed with error: %@", [error localizedDescription]);                                             }                                             if (result == AVAssetImageGeneratorCancelled) {                                                 NSLog(@"Canceled");                                             }                                         }];             }

这个破东西我看了两天资料  好像别人都没有问题,网上搜不到有问这个问题的(ps:估计是我太笨了,别人都没问题)
终于找到解决办法了
官网文档有一句话   https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVAssetImageGenerator_Class/Reference/Reference.html

The actual time of a generated image is within the range [requestedTime-requestedTimeToleranceBefore, requestedTime+requestedTimeToleranceAfter] and may differ from the requested time for efficiency.

然后找到了requestedTimeToleranceAfter这个属性
http://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVAssetImageGenerator_Class/Reference/Reference.html#//apple_ref/occ/instp/AVAssetImageGenerator/requestedTimeToleranceAfter

里面有一句话说明
Set the values of requestedTimeToleranceBefore and requestedTimeToleranceAfter to kCMTimeZero to request frame-accurate image generation; this may incur additional decoding delay.

加上
self.myImageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
self.myImageGenerator.requestedTimeToleranceAfter = kCMTimeZero;

之后 时间就比较准确了  只剩一点微小的误差  不过完全可以接受
0 0