如何从视频中获取最后一帧?
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)
【讨论】:
以上是关于如何从视频中获取最后一帧?的主要内容,如果未能解决你的问题,请参考以下文章