ビデオからサムネイルを取得して、テーブルビューに表示しようとしています。これが私のコードです:
- (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;
}
しかし、画像は常に黒に戻ります。どうしましたか?
これを使用してください: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でこれを使用する必要があります。画像を配列またはモデルに保存し、サムネイルが作成されたら、それがキャッシュ/配列を参照していることを確認して、cellForRowAtIndexPath
がUITableView
のスクロールに遅れを生じさせないようにする必要があります。
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
}
}
//(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;
このコードを使用するだけです。ビデオの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;
}
願わくば、これがあなたが探しているものです。どんな懸念も私に戻ってきます。 :)
「動画からサムネイルを生成する」のリンクを確認してください
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)
}
}
@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);
})
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
}
}
このコードは機能しています。