如何从视频中获取最后一帧?

Posted

技术标签:

【中文标题】如何从视频中获取最后一帧?【英文标题】:How to get last frame from video? 【发布时间】:2015-08-17 09:49:27 【问题描述】:

我想要最后一帧视频,我的代码如下所示:

let asset : AVURLAsset = AVURLAsset(URL: videoURL, options: nil)
    let generate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
    generate.appliesPreferredTrackTransform = true

    var err : NSError? = nil
    var lastFrameTime = Int64(CMTimeGetSeconds(asset.duration))
    let time : CMTime = CMTimeMake(lastFrameTime, 30)
    let imgRef : CGImageRef = generate.copyCGImageAtTime(time, actualTime: nil, error: &err)
    let img : UIImage = UIImage(CGImage: imgRef)!

但是我没有得到最后一帧,我得到了第一帧,请为此提供解决方案。

【问题讨论】:

【参考方案1】:

我使用 Pooja 的代码作为起点,但它没有得到最后一帧。它得到接近最后一帧的东西。这是我获取实际最后一帧的解决方案。如果帧精度很重要,那么您必须使用:

imageGenerator.requestedTimeToleranceBefore = kCMTimeZero
imageGenerator.requestedTimeToleranceAfter = kCMTimeZero

请注意,生成此帧准确的最后一帧可能需要更长的时间,因此您可能希望在后台线程上执行此操作。

这是我正在使用的代码:

let imageGenerator = AVAssetImageGenerator(asset: asset!)
imageGenerator.appliesPreferredTrackTransform = true
imageGenerator.requestedTimeToleranceAfter = kCMTimeZero
imageGenerator.requestedTimeToleranceBefore = kCMTimeZero

let composition = AVVideoComposition(propertiesOfAsset: asset!)
let time = CMTimeMakeWithSeconds(asset!.duration.seconds, composition.frameDuration.timescale)

do 
    let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)

catch let error as NSError 
    print("Image generation failed with error \(error)")

希望这会有所帮助。

【讨论】:

【参考方案2】:

您可以在 Objective-C 中获取视频的最后一帧,如下所述:-

    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
    AVAssetImageGenerator *generate = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
    generate.appliesPreferredTrackTransform = YES;

    NSError *error;

    int64_t lastFrameTime = CMTimeGetSeconds(asset.duration)*60.0;
    CMTime time = CMTimeMake(lastFrameTime, 2);
    CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:nil error:&error];
    UIImage *image = [UIImage imageWithCGImage:imgRef];

【讨论】:

请发布 OP 提出的有关 Swift 的问题的相关代码 我看不出客观的 c 代码有什么帮助。【参考方案3】:

我已经解决了这个问题,只从视频中获取最后一帧代码如下:

  let asset : AVURLAsset = AVURLAsset(URL: videoURL, options: nil)
    let generate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
    generate.appliesPreferredTrackTransform = true

    var err : NSError? = nil
    var lastFrameTime = Int64(CMTimeGetSeconds(asset.duration)*60.0)
    let time : CMTime = CMTimeMake(lastFrameTime, 2)
    let imgRef : CGImageRef = generate.copyCGImageAtTime(time, actualTime: nil, error: &err)
    let img : UIImage = UIImage(CGImage: imgRef)!

这就是我如何在 img 变量中获取视频的最后一张图片。

【讨论】:

这里为什么使用preferredTimeScale的硬编码值2? 我还在获取第一帧【参考方案4】:

接受的答案产生第一帧。

此代码有效(objective-c)

AVAsset* asset = [AVAsset assetWithURL:videoURL];
AVAssetImageGenerator *generate = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
generate.requestedTimeToleranceAfter = kCMTimeZero;
generate.requestedTimeToleranceBefore = kCMTimeZero;
generate.appliesPreferredTrackTransform = YES;

NSError *error;
CMTime time = asset.duration;
CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:nil error:&error];
UIImage *image = [UIImage imageWithCGImage:imgRef];

这里的主要内容是:

generate.requestedTimeToleranceAfter = kCMTimeZero;
generate.requestedTimeToleranceBefore = kCMTimeZero;

CMTime time = asset.duration;

【讨论】:

【参考方案5】:

经过多次尝试,我终于得到了视频的最后一帧。

let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true

// Make sure you set the next two properties. 
// It didn't work for me without this two parameters!
imageGenerator.requestedTimeToleranceBefore = .zero
imageGenerator.requestedTimeToleranceAfter = .positiveInfinity

let lastFrameTime = Int64(CMTimeGetSeconds(asset.duration) * 60)
time = CMTime(value: lastFrameTime, timescale: 2)

guard let imageRef = try? imageGenerator.copyCGImage(at: time, actualTime: nil) else  
    return


let thumbnailImage = UIImage(cgImage: imageRef)

【讨论】:

以上是关于如何从视频中获取最后一帧?的主要内容,如果未能解决你的问题,请参考以下文章

如何从视频中提取某一帧的图像

如何从视频中提取某一帧的图像

如何从使用directx c# visual studio播放的视频中获取和处理每一帧(位图图像​​)

如何截取视频的第一帧图片

从正在写入的视频 .avi 文件中读取

如何通过 OpenCV 和 Python 通过索引从视频中获取帧?