J'essaie d'acquérir une vignette (de la première image) à partir d'une vidéo prise depuis un appareil photo iphone 3GS afin de pouvoir l'afficher. Comment faire ça?
La réponse à cette question est qu’on peut maintenant avec iOS 4.0 obtenir des vignettes en utilisant AVFoundation, le code suivant où l’URL de la propriété de la classe est l’URL du film fera l'affaire (vous pouvez obtenir la vignette à tout moment, dans l'exemple temps 0)
-(void)generateImage
{
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:self.url options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform=TRUE;
[asset release];
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);
}
[button setImage:[UIImage imageWithCGImage:im] forState:UIControlStateNormal];
thumbImg=[[UIImage imageWithCGImage:im] retain];
[generator release];
};
CGSize maxSize = CGSizeMake(320, 180);
generator.maximumSize = maxSize;
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];
}
-(UIImage *)generateThumbImage : (NSString *)filepath
{
NSURL *url = [NSURL fileURLWithPath:filepath];
AVAsset *asset = [AVAsset assetWithURL:url];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = [asset duration];
time.value = 0;
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // CGImageRef won't be released by ARC
return thumbnail;
}
vous pouvez obtenir le cadre en utilisant time.value supposons que vous vouliez 1 seconde image puis utilisez le
time.value = 1000 //Time in milliseconds
NSURL *videoURL = [NSURL fileURLWithPath:url];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
UIImage *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
//Player autoplays audio on init
[player stop];
[player release];
Vérifiez ce lien pour une alternative: thumbnailImageAtTime: maintenant obsolète - Quelle est l’alternative?
Meilleure méthode que j'ai trouvée ... MPMoviePlayerController thumbnailImageAtTime:timeOption
Vous pouvez générer dans Swift de deux manières: 1. AVFoundation 2. MPMoviePlayerController
1.
func generateThumnail(url : NSURL) -> UIImage{
var asset : AVAsset = AVAsset.assetWithURL(url) as AVAsset
var assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
var error : NSError? = nil
var time : CMTime = CMTimeMake(1, 30)
var img : CGImageRef = assetImgGenerate.copyCGImageAtTime(time, actualTime: nil, error: &error)
var frameImg : UIImage = UIImage(CGImage: img)!
return frameImg
}
2.
override func viewDidLoad() {
super.viewDidLoad()
var moviePlayer : MPMoviePlayerController! = MPMoviePlayerController(contentURL: moviePlayManager.movieURL)
moviePlayer.view.frame = CGRect(x: self.view.frame.Origin.x, y: self.view.frame.Origin.y, width:
self.view.frame.size.width, height: self.view.frame.height)
moviePlayer.fullscreen = true
moviePlayer.controlStyle = MPMovieControlStyle.None
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "videoThumbnailIsAvailable:",
name: MPMoviePlayerThumbnailImageRequestDidFinishNotification,
object: nil)
let thumbnailTimes = 3.0
moviePlayer.requestThumbnailImagesAtTimes([thumbnailTimes],
timeOption: .NearestKeyFrame)
}
func videoThumbnailIsAvailable(notification: NSNotification){
if let player = moviePlayer{
let thumbnail =
notification.userInfo![MPMoviePlayerThumbnailImageKey] as? UIImage
if let image = thumbnail{
/* We got the thumbnail image. You can now use it here */
println("Thumbnail image = \(image)")
}
}
Pour Swift 3.0
func createThumbnailOfVideoFromFileURL(_ strVideoURL: String) -> UIImage?{
let asset = AVAsset(url: URL(string: strVideoURL)!)
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 {
/* error handling here */
}
return nil }
Swift 2 code:
func previewImageForLocalVideo(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
}
}
Peut-être que cela est utile pour quelqu'un d'autre confronté au même problème. J'avais besoin d'une solution simple pour créer une vignette pour les images, les PDF et les vidéos. Pour résoudre ce problème, j'ai créé la bibliothèque suivante.
https://github.com/prine/ROThumbnailGenerator
L'utilisation est très simple:
var thumbnailImage = ROThumbnail.getThumbnail(url)
Il a en interne trois implémentations différentes et en fonction de l’extension du fichier, il crée la vignette. Vous pouvez facilement ajouter votre propre implémentation si vous avez besoin d'un créateur de vignettes pour une autre extension de fichier.
Swift 2.1 Obtenir des vignettes aux intervalles souhaités
func getPreviewImageForVideoAtURL(videoURL: NSURL, atInterval: Int) -> UIImage? {
print("Taking pic at \(atInterval) second")
let asset = AVAsset(URL: videoURL)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(Float64(atInterval), 100)
do {
let img = try assetImgGenerate.copyCGImageAtTime(time, actualTime: nil)
let frameImg = UIImage(CGImage: img)
return frameImg
} catch {
/* error handling here */
}
return nil
}
Vous obtiendrez Thumbnail Image From URL lorsque vous changerez "fileURLWithPath" en "URLWithString".
Dans mon cas, cela a fonctionné comme ça.
NSURL *url = [NSURL URLWithString:filepath];
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;
Swift 4
func generateThumbnail(for asset:AVAsset) -> UIImage? {
let assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMake(value: 1, timescale: 2)
let img = try? assetImgGenerate.copyCGImage(at: time, actualTime: nil)
if img != nil {
let frameImg = UIImage(cgImage: img!)
return frameImg
}
return nil
}
Comment utiliser:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true) {
switch mediaType {
case kUTTypeMovie:
guard info[UIImagePickerController.InfoKey.mediaType] != nil, let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL else { return }
let asset = AVAsset(url: url)
guard let img = self.generateThumbnail(for: asset) else {
print("Error: Thumbnail can be generated.")
return
}
print("Image Size: \(img.size)")
break
default:
break
}
}
}