web-dev-qa-db-ja.com

iOS-再生せずにビデオからサムネイルを取得するにはどうすればよいですか?

ビデオからサムネイルを取得して、テーブルビューに表示しようとしています。これが私のコードです:

- (UIImage *)imageFromVideoURL:(NSURL *)contentURL {
    AVAsset *asset = [AVAsset assetWithURL:contentURL];

    //  Get thumbnail at the very start of the video
    CMTime thumbnailTime = [asset duration];
    thumbnailTime.value = 25;

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

しかし、画像は常に黒に戻ります。どうしましたか?

11
TienLe

これを使用してください: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 {
        return UIImage(named: "ico_placeholder")
    }
}

重要な注意:

リソースが豊富なため、ifelseでこれを使用する必要があります。画像を配列またはモデルに保存し、サムネイルが作成されたら、それがキャッシュ/配列を参照していることを確認して、cellForRowAtIndexPathUITableViewのスクロールに遅れを生じさせないようにする必要があります。

7

AVAssetの拡張関数としてSwift 5を使用:

import AVKit

extension AVAsset {

    func generateThumbnail(completion: @escaping (UIImage?) -> Void) {
        DispatchQueue.global().async {
            let imageGenerator = AVAssetImageGenerator(asset: self)
            let time = CMTime(seconds: 0.0, preferredTimescale: 600)
            let times = [NSValue(time: time)]
            imageGenerator.generateCGImagesAsynchronously(forTimes: times, completionHandler: { _, image, _, _, _ in
                if let image = image {
                    completion(UIImage(cgImage: image))
                } else {
                    completion(nil)
                }
            })
        }
    }
}

使用法:

            AVAsset(url: url).generateThumbnail { [weak self] (image) in
                DispatchQueue.main.async {
                    guard let image = image else { return }
                    self?.imageView.image = image
                }
            }
5
Samuël
//(Local URL)
NSURL *videoURL = [NSURL fileURLWithPath:filepath];// filepath is your video file path 



AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
AVAssetImageGenerator *generateImg = [[AVAssetImageGenerator alloc] initWithAsset:asset];
NSError *error = NULL;
CMTime time = CMTimeMake(1, 1);
CGImageRef refImg = [generateImg copyCGImageAtTime:time actualTime:NULL error:&error];
NSLog(@"error==%@, Refimage==%@", error, refImg);

UIImage *frameImage= [[UIImage alloc] initWithCGImage:refImg];
return frameImage;
3
Mohit Tomar

このコードを使用するだけです。ビデオのURLを渡して、画像を取得します。

+(UIImage *)getPlaceholderImageFromVideo:(NSString *)videoURL {
    NSURL *url = [NSURL URLWithString:videoURL];
    AVAsset *asset = [AVAsset assetWithURL:url];
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    CMTime time = [asset duration];
    time.value = 0;
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return thumbnail;
}

願わくば、これがあなたが探しているものです。どんな懸念も私に戻ってきます。 :)

3
Meet Doshi

「動画からサムネイルを生成する」のリンクを確認してください

https://littlebitesofcocoa.com/115-generate-thumbnails-from-videos

アプリがビデオの内容の1つ以上のサムネイル(小さな静止画像のプレビュー)を表示する必要があることは非常に一般的です。ただし、動画の送信元によっては、作成済みのサムネイルに簡単にアクセスできない場合があります。 AVAssetImageGeneratorを使用して独自のものを取得する方法を見てみましょう。ビデオの単純なNSURLから始めます。これは、ローカルでもリモートでもかまいません。それを使用してAVAssetを作成し、それを新しいAVAssetImageGeneratorオブジェクトに作成します。サムネイルが正しい方向になるように、優先変換を適用するようにジェネレーターを構成します。

import AVFoundation

if let asset = AVAsset(URL: videoURL) {
   let durationSeconds = CMTimeGetSeconds(asset.duration)
   let generator = AVAssetImageGenerator(asset: asset)

   generator.appliesPreferredTrackTransform = true

   let time = CMTimeMakeWithSeconds(durationSeconds/3.0, 600)
   var thumbnailImage: CGImageRef 
   generator.generateCGImagesAsynchronouslyForTimes([NSValue(CMTime: time)]) { 
       (requestedTime: CMTime, thumbnail: CGImage?, actualTime: CMTime, result: AVAssetImageGeneratorResult, error: NSError?) in
      self.videoThumbnailImageView.image = UIImage(CGImage: thumbnail)
    }
}
2
Disha

@Dishaの答えのSwift4コード:

let imageGenerator = AVAssetImageGenerator(asset: avAsset)
                let time = CMTime(seconds: seconds, preferredTimescale: 600)
                let times = [NSValue(time: time)]
                imageGenerator.generateCGImagesAsynchronously(forTimes: times, completionHandler: {
                    requestedTime, image, actualTime, result, error in
                    guard let cgImage = image else
                    {
                        print("No image!")
                        return
                    }
                    let uiImage = UIImage(cgImage: cgImage)
                    UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil);
                })
1
spfursich
func getThumbnailFrom(path: URL) -> UIImage? {

        do {
            let asset = AVURLAsset(url: path , options: nil)
            let imgGenerator = AVAssetImageGenerator(asset: asset)
            imgGenerator.appliesPreferredTrackTransform = true
            let timestamp = asset.duration
            print("Timestemp:   \(timestamp)")
            let cgImage = try imgGenerator.copyCGImage(at: timestamp, actualTime: nil)
            let thumbnail = UIImage(cgImage: cgImage)
            return thumbnail
            } catch let error {
            print("*** Error generating thumbnail: \(error.localizedDescription)")
            return nil
          }
        }

このコードは機能しています。

0
Vikas Verma