在 iPhone SDK 中从视频 URL 创建缩略图

29

我试图从视频URL中获取缩略图。该视频是使用m3u8格式的流(HLS)。 我已经尝试了MPMoviePlayerController的requestThumbnailImagesAtTimes,但没有成功。有人有解决这个问题的方案吗?如果有,你是如何做到的?


您可以访问下面给出的链接。非常有用。 http://developer.apple.com/library/IOs/#documentation/AVFoundation/Reference/AVAssetImageGenerator_Class/Reference/Reference.html#//apple_ref/occ/cl/AVAssetImageGenerator - Ajeet Pratap Maurya
请检查一下:https://dev59.com/0VwY5IYBdhLWcg3wYW1X#45164607 - Meet Doshi
9个回答

48

如果您不想使用MPMoviePlayerController,可以这样做:

    AVAsset *asset = [AVAsset assetWithURL:sourceURL];
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
    CMTime time = CMTimeMake(1, 1);
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);  // CGImageRef won't be released by ARC

以下是 Swift 的一个示例:

func thumbnail(sourceURL sourceURL:NSURL) -> UIImage {
    let asset = AVAsset(URL: sourceURL)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    let time = CMTime(seconds: 1, preferredTimescale: 1)

    do {
        let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
        return UIImage(CGImage: imageRef)
    } catch {
        print(error)
        return UIImage(named: "some generic thumbnail")!
    }
}

我更喜欢使用AVAssetImageGenerator而不是MPMoviePlayerController,因为它是线程安全的,并且您可以同时实例化多个。


3
使用-copyCGImageAtTime:actualTime:error:获取的CGImageRef需要使用CGImageRelease()释放。 - rbrown
1
给我报了一个错误 AVErrorOperationNotSupportedForAsset。请帮忙解决。 - ruyamonis346
4
顺便提一下,AV 需要 AVFoundation 框架,而 CMTime 需要 CoreMedia 框架(这两个我曾经遇到过些许麻烦)。干杯! - Heavy_Bullets
好的方法,但它可能会错过视频方向,就像我的情况一样。 - Skie
1
完美...这是iOS 7的thumbnailImageAtTime已经被弃用的一个很好的替代方案。 - Marcos Reboucas
请在这里给我建议:https://stackoverflow.com/questions/47617130/error-getting-same-video-thumbnail-image-every-time-in-swift3-ios - Anand Gautam

25
从视频url获取缩略图。
    NSString *strVideoURL = @"http://www.xyzvideourl.com/samplevideourl";
    NSURL *videoURL = [NSURL URLWithString:strVideoURL] ;
    MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
    UIImage  *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
    player = nil;

strVideoURL替换您的视频URL字符串。 您将从video获得缩略图作为输出。 缩略图是UIImage类型的数据!

将视频的URL字符串替换为strVideoURL,然后从video 获取缩略图作为输出。缩略图是UIImage类型的数据!


2
我正在使用这段代码从YouTube的URL中获取视频缩略图,但它没有给我图片。我想在表格视图中放置缩略图,您能帮我吗? - Jaspreet Singh
我认为你无法从类似于www.youtube.com/watch?v=xxxxxxx的Youtube URL中获取视频。 - Shinigamae
我正在使用此URL:http://www.sciencentral.com/news/image_db/2024515/NNM2212_AntPower_MSTR.mov,但是无法获取缩略图。请帮忙解决。 - ruyamonis346

9
-(UIImage *)loadThumbNail:(NSURL *)urlVideo
{    
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:urlVideo options:nil];
    AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generate.appliesPreferredTrackTransform=TRUE;
    NSError *err = NULL;
    CMTime time = CMTimeMake(1, 60);
    CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
    NSLog(@"err==%@, imageRef==%@", err, imgRef);
    return [[UIImage alloc] initWithCGImage:imgRef];
}

在您的项目中添加AVFoundation框架,不要忘记导入<AVFoundation/AVFoundation.h>,您需要将文档目录中保存视频的路径作为参数传递,并接收图像作为UIImage

我没有把视频保存在文档目录中,也不想保存。我想从URL生成图像。这可行吗? - Arpit B Parekh
你好 @ArpitBParekh,无法在线生成缩略图,即不保存在文档目录中。如果这个答案对你有用,请接受我的回答 :) - Ankit Goyal
谢谢回复。但是在搜索后,我已经做到了。让我发布链接。 - Arpit B Parekh
我不知道,但它有效。 - Arpit B Parekh
UI会卡顿几秒钟。但是如果我把下面的代码放在NSTimer(另一个线程)上调用,UI就不会卡顿了。 - Arpit B Parekh

4
使用以下代码,您可以从视频url获取缩略图:

你可以使用下面的代码从视频url中获取缩略图

MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
UIImage  *thumbnail = [player thumbnailImageAtTime:0.0 timeOption:MPMovieTimeOptionNearestKeyFrame];

1
在iOS 7中已经被技术上弃用,但它仍然可以使用,而且我从来没有弄清楚如何正确使用-requestThumbnailImagesAtTimes:timeOption:。 - Rob R.
4
在 iOS7 中推荐使用什么? - Dejell

2
也许对于面临相同问题的其他人有所帮助。我需要一个易于创建图像、PDF和视频缩略图的简单解决方案。为了解决这个问题,我已经创建了以下Swift库:https://github.com/prine/ROThumbnailGenerator
使用非常简单: var thumbnailImage = ROThumbnail.getThumbnail(url)
它内部有三种不同的实现,根据文件扩展名创建缩略图。如果你需要为另一种文件扩展名创建缩略图生成器,可以很容易地添加自己的实现。

2

对于 Swift 5,您可以按照以下方式获取:

首先,在 ViewController 中导入 AVKit 或 AVFoundation

import AVKit

代码:

// Get Thumbnail Image from URL
private func getThumbnailFromUrl(_ url: String?, _ completion: @escaping ((_ image: UIImage?)->Void)) {

    guard let url = URL(string: url ?? "") else { return }

    DispatchQueue.main.async {
        let asset = AVAsset(url: url)
        let assetImgGenerate = AVAssetImageGenerator(asset: asset)
        assetImgGenerate.appliesPreferredTrackTransform = true

        let time = CMTimeMake(value: 2, timescale: 1)
        do {
            let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
            let thumbnail = UIImage(cgImage: img)
            completion(thumbnail)
        } catch {
            print("Error :: ", error.localizedDescription)
            completion(nil)
        }
    }
}

用法

@IBOutlet weak imgThumbnail: ImageView! 

然后调用 getThumbnailFromUrl 方法,并将 URL 作为 String 参数传递。

self.getThumbnailFromUrl(videoURL) { [weak self] (img) in

    guard let `self` = self else { return }

    if let img = img {
        self.imgThumbnail.image = img
    }
}

谢谢您


2

对于Swift 3.0:

  func generateThumbnailForVideoAtURL(filePathLocal: NSString) -> UIImage? {
    let vidURL = NSURL(fileURLWithPath:filePathLocal as String)
    let asset = AVURLAsset(url: vidURL as URL)
    let generator = AVAssetImageGenerator(asset: asset)
    generator.appliesPreferredTrackTransform = true

    let timestamp = CMTime(seconds: 1, preferredTimescale: 60)

    do {
        let imageRef = try generator.copyCGImage(at: timestamp, actualTime: nil)
        let frameImg    : UIImage = UIImage(cgImage: imageRef)
        return frameImg
    } catch let error as NSError {
        print("Image generation failed with error ::\(error)")
        return nil
    }
}

2

Swift 3 版本:

func createThumbnailOfVideoFromFileURL(videoURL: String) -> UIImage? {
    let asset = AVAsset(url: URL(string: videoURL)!)
    let assetImgGenerate = AVAssetImageGenerator(asset: asset)
    assetImgGenerate.appliesPreferredTrackTransform = true
    let time = CMTimeMakeWithSeconds(Float64(1), 100)
    do {
        let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
        let thumbnail = UIImage(cgImage: img)
        return thumbnail
    } catch {
        // Set a default image if Image is not acquired
        return UIImage(named: "ico_placeholder")
    }
}

为什么你在使用硬编码值100的preferredTimeScale? - Anand Gautam

0

使用AVAssetImageGenerator的Swift 2代码:

func thumbnailImageForVideo(url:NSURL) -> UIImage?
{
    let asset = AVAsset(URL: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true

    var time = asset.duration
    //If possible - take not the first frame (it could be completely black or white on camara's videos)
    time.value = min(time.value, 2)

    do {
        let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
        return UIImage(CGImage: imageRef)
    }
    catch let error as NSError
    {
        print("Image generation failed with error \(error)")
        return nil
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接