我正在尝试从视频中获取第一个缩略图。
我尝试了以下内容:
ONE
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_moviePath] options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *thumb = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
NSLog(@"the error is %@: image is %@: url is %@: ",error,_mainThumbnail,[NSURL fileURLWithPath:_moviePath] );
但是,我的日志是:
the error is (null): image is (null):
url is file:///private/var/mobile/Applications/D1293BDC-EA7E-4AC7-AD3C-1BA3548F37D6/tmp/trim.6F0C4631-E5E8-43CD-BF32-9B8F09D4ACF1.MOV:
TWO
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_moviePath] options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform=TRUE;
CMTime thumbTime = CMTimeMakeWithSeconds(0,30);
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result != AVAssetImageGeneratorSucceeded) {
NSLog(@"couldn't generate thumbnail, error:%@", error);
}
_mainThumbnail.image = [UIImage imageWithCGImage:im];
NSLog(@"thumbnails %@ ",_mainThumbnail.image);
};
CGSize maxSize = CGSizeMake(320, 180);
generator.maximumSize = maxSize;
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];
日志记录为空。
为什么图像为空?我查看了其他论坛,他们建议使用我已经在使用的fileURLWithPath。
我正在使用ios7
答案 0 :(得分:19)
您可以尝试此方法。它会在给定的网址上显示视频的第一帧,并将其返回为UIImage
。
- (UIImage *)thumbnailFromVideoAtURL:(NSURL *)url
{
AVAsset *asset = [AVAsset assetWithURL:url];
// Get thumbnail at the very start of the video
CMTime thumbnailTime = [asset duration];
thumbnailTime.value = 0;
// Get image from the video at the given time
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:thumbnailTime actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}
该方法不检查错误,因为我的代码使用它是正常的,如果有任何失败,只返回nil
。
修改:澄清CMTime
值
CMTime
已
timescale
- 将此视为视频的FPS(每秒帧数)(25 FPS - > 1s视频有25个视频帧)value
- 识别具体框架。在上面的代码中,这表示您想要使用缩略图的哪个帧。要在准确时间计算帧,您必须进行此计算:
value = timescale * seconds_to_skip
相当于
"Frame of the video to take" = "FPS" * "Number of seconds to skip"
如果您想拍摄视频第2帧的第1帧,您实际上要跳过视频的第1秒。所以你会使用:
CMTime thumbnailTime = [asset duration];
thumbnailTime.value = thumbnailTime.timescale * 1;
另一种观点:你想跳过视频的前1个而不是缩略图。即在25 FPS上,你想跳过25帧。所以CMTime.value = 25
(跳过25帧)。
答案 1 :(得分:2)
以防有人犯了与我相同的错误:
检查是否使用适当的方法生成URL
。您不应该对该文件的本地和网络URL
进行反对。
如果是本地视频文件,请使用以下代码:
NSURL *movieURL = [NSURL fileURLWithPath:_moviePath];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];
如果是来自互联网的视频文件,请使用以下代码:
NSURL *movieURL = [NSURL URLWithString:_moviePath];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];
答案 2 :(得分:0)
我成功使用此代码段,从视频中获取屏幕截图:
- (UIImage *)currentItemScreenShot
{
AVURLAsset *asset = (AVURLAsset *)playerItem_.asset;
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
CGImageRef thumb = [imageGenerator
copyCGImageAtTime:CMTimeMakeWithSeconds(0, 1.0)
actualTime:NULL
error:NULL];
UIImage *image = [UIImage imageWithCGImage:thumb];
CGImageRelease(thumb);
[imageGenerator release];
return image;
}
但是在我的情况下 - 我在应用程序中成功导入视频后两秒钟这样做了。 (它有图像方向的问题,如果我在导入视频后这样做,有时会返回没有图像或半图像。)
答案 3 :(得分:0)
Swift 版本接受的答案@Lukas Kukacka回答:
func thumbnailFromVideoAtURL(url: URL) -> UIImage?{
let asset = AVAsset(url: url)
// Get thumbnail at the very start of the video
var thumbnailTime: CMTime = asset.duration
thumbnailTime.value = 0
// Get image from the video at the given time
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true // this rotates the image to the correct position the camera took it in
do{
let imageRef = try imageGenerator.copyCGImage(at: thumbnailTime, actualTime: nil)
return UIImage(cgImage: imageRef)
}catch let err as NSError{
print(err.localizedDescription)
}
return nil
}
<强>加成强>
在let imageGenerator = AVAssetImageGenerator(asset: asset
下,我添加了:
imageGenerator.appliesPreferredTrackTransform = true
我遇到了一个问题,我会以纵向方式录制,获取缩略图,然后它会在横向上返回。 This answer解决了这个问题。
答案 4 :(得分:0)
SWIFT 5.2版本:
您可以找到我的原始帖子here,是我从rozochkin's answer那里汲取灵感的。
func getCurrentFrame() -> UIImage? {
guard let player = self.player, let avPlayerAsset = player.currentItem?.asset else {return nil}
let assetImageGenerator = AVAssetImageGenerator(asset: avPlayerAsset)
assetImageGenerator.requestedTimeToleranceAfter = .zero
assetImageGenerator.requestedTimeToleranceBefore = .zero
assetImageGenerator.appliesPreferredTrackTransform = true
let imageRef = try! assetImageGenerator.copyCGImage(at: player.currentTime(), actualTime: nil)
let image = UIImage(cgImage: imageRef)
return image
}
重要说明:
requestedTimeToleranceAfter 和 requestedTimeToleranceBefore 应该设置为.zero,因为根据源代码,“生成图像的实际时间可能与[...]要求的效率时间”。
appliesPreferredTrackTransform 必须设置为 TRUE (默认为FALSE),否则会出现帧旋转不良。将此属性设置为TRUE,您将获得在播放器中真正看到的内容。