从视频中截取缩略图始终返回null

时间:2013-10-06 18:33:17

标签: iphone ios objective-c cocoa-touch ios6

我正在尝试从视频中获取第一个缩略图。

我尝试了以下内容:

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

5 个答案:

答案 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,您将获得在播放器中真正看到的内容。