【问题标题】:iOS Take Multiple Screen ShotsiOS 多张截图
【发布时间】:2015-04-03 02:34:04
【问题描述】:

我有一个包含视频的 NSURL,我想每秒钟录制十次该视频的帧。我有代码可以捕捉我的播放器的图像,但我无法将其设置为每秒捕捉 10 帧。我正在尝试这样的事情,但它返回了相同的视频初始帧,正确的次数?这是我所拥有的:

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

但是我没有获取视频当前时间 i 的帧,而是获取了初始帧?

如何获得每秒 10 次的视频帧?

感谢您的帮助:)

【问题讨论】:

    标签: ios xcode video camera


    【解决方案1】:

    您正在获取初始帧,因为您尝试借助浮点值创建 CMTime:

    CMTime time = CMTimeMake(i, 10);
    

    由于CMTimeMake函数将int64_t值作为第一个参数,你的float值会被四舍五入为int,你会得到不正确的结果。

    让我们稍微修改一下代码:

    1) 首先,您需要找到需要从视频中获取的总帧数。您写道,您需要每秒 10 帧,所以代码将是:

    int requiredFramesCount = seconds * 10;
    

    2)接下来,您需要找到一个值,该值将在每一步中增加您的 CMTime 值:

    int64_t step = vidLength.value / requiredFramesCount;
    

    3) 最后,您需要将 requestedTimeToleranceBefore 和 requestedTimeToleranceAfter 设置为 kCMTimeZero,以获得精确时间的帧:

    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;
    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
    

    您的代码如下所示:

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

    【讨论】:

    【解决方案2】:

    使用CMTimeMake(A, B),您可以存储一个有理数、一个精确的分数 A / B 秒,并且此函数的第一个参数采用 int 值。对于 20 秒的视频,您将在周期的最后一次迭代中捕获具有时间 ((int) 19.9) / 10 = 1.9 秒的帧。使用CMTimeMakeWithSeconds(i, NSEC_PER_SEC)函数修复这个时间问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 1970-01-01
      • 2013-11-03
      • 2012-08-12
      • 1970-01-01
      • 2016-04-10
      相关资源
      最近更新 更多