從視頻獲取縮略圖總是返回null

[英]Taking thumbnail image from video always returns null


I am trying to get the first thumbnail from a video.

我想從一段視頻中得到第一個縮略圖。

I tried the following:

我試着以下:

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] );

However, my log is:

然而,我的日志:

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

The log thumnails null.

日志thumnails null。

Why is the image null? I looked in other forums, and they suggested to use fileURLWithPath -which I am already using.

為什么圖像為空?我查看了其他論壇,他們建議使用fileURLWithPath——我已經在使用它了。

I am using ios7

我用ios7

4 个解决方案

#1


18  

You can try this method. It takes the first frame of the video at the given URL and returns it as UIImage.

你可以試試這個方法。它在給定的URL處獲取視頻的第一幀並將其作為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;
}

The method does not check for errors as my code using it is OK with just nil returned if anything fails.

該方法不檢查錯誤,因為我的代碼使用它是OK的,如果有任何失敗,只返回nil。


Edit: Clarification of CMTime values

編輯:澄清CMTime值。

CMTime has

CMTime已經

  • timescale - think about this as a FPS (frames per second) of the video (25 FPS -> 1s of the video has 25 video frames)
  • timescale——把這個看作是視頻的FPS(每秒幀數)(25個FPS -> 1的視頻有25個視頻幀)
  • value - identification of concrete frame. In the code above, this says which frame you want to take thumbnail of.
  • 價值——混凝土框架的識別。在上面的代碼中,這表示您想取縮略圖的框架。

For calculation of frame at exact time, you have to make this calculation:

對於精確時間的框架計算,你需要做如下計算:

value = timescale * seconds_to_skip

which is the equivalent to

它等於什么

"Frame of the video to take" = "FPS" * "Number of seconds to skip"

If you want to take for example 1st frame of 2nd second of the video, you want in fact to skip 1st second of the video. So you would use:

如果你想以視頻的第一幀為例,你想要跳過視頻的第一幀。所以你會使用:

CMTime thumbnailTime = [asset duration];
thumbnailTime.value = thumbnailTime.timescale * 1;

Another look: you want to skip first 1s of the video and than take a thumbnail. I.e. on 25 FPS, you want to skip 25 frames. So CMTime.value = 25 (skip 25 frames).

另一種看法是:你想跳過視頻的前一個1,而不是只看一個縮略圖。也就是說,在25幀每秒,你要跳過25幀。所以CMTime。值= 25(跳過25幀)。

#2


1  

Just in case someone made the same mistake as I did:

以防有人犯和我一樣的錯誤:

Check out if the URL is generated using appropriate method. You shouldn't get counfused for local and web URLs of the file.

檢查URL是否使用適當的方法生成。您不應該為文件的本地和web url進行計數。

In case of local video file, use below code:

如果是本地視頻文件,請使用以下代碼:

NSURL *movieURL = [NSURL fileURLWithPath:_moviePath];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];

In case of video file from internet, use below code:

如有來自互聯網的視頻文件,請使用以下代碼:

NSURL *movieURL = [NSURL URLWithString:_moviePath];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];

#3


0  

I successfully use this snippet, to get a screenshot from video:

我成功地使用了這個片段,從視頻中獲得了一個截圖:

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

But in my case - I am doing it two seconds after video was successfully imported in application. ( It had problems with picture orientation, sometimes returned no image or half image if I did it once video was imported).

但在我的例子中,我是在視頻被成功導入應用程序兩秒鍾后做的。(它在圖片定位上有問題,有時候在導入視頻后沒有返回圖像或半圖像)。

#4


0  

Swift version of the accepted answer @Lukas Kukacka answer:

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
}

Bonus

獎金

Under let imageGenerator = AVAssetImageGenerator(asset: asset) I added:

在let imageGenerator = AVAssetImageGenerator(asset: asset)下,我添加了:

imageGenerator.appliesPreferredTrackTransform = true

I had a problem where I would record in portrait, get the thumbnail image and it would get returned in landscape. This answer solved that problem.

我有個問題,我在豎屏中記錄,得到縮略圖,然后在橫屏中返回。這個答案解決了那個問題。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/10/06/72545c2a8c2664d37c5263158b582280.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com