2010-11-28 56 views
16

Je joue une vidéo avec AVPlayer. Cela fonctionne bien.Obtenir UIImage à partir du CALayer attaché à AVPlayer (extraire le cadre de la lecture de la vidéo)

Maintenant, je veux obtenir un UIImage de la lecture de la vidéo (quand je pousse un bouton pour le moment).

Attaché à mon AVPlayer il y a un CALayer qui est utilisé pour afficher la vidéo sur mon UIView. Mon idée est d'obtenir un UIImage de CALayer pendant la lecture de la vidéo.

Je le fais avec le code d'une autre question:

UIImage from CALayer - iPhone SDK

Cependant, mon UIImage est vide. La résolution est bonne mais elle est complètement blanche !!!

Il semble que la vidéo n'écrit pas le contenu de mon CALayer.

Quelqu'un peut-il m'aider? Merci

+2

pourrions-nous voir le code qui invoque la méthode pour créer l'image? –

Répondre

1

Essayez d'obtenir l'image à partir du fichier vidéo à instance spécifiée en utilisant la AVAssetImageGenerator:

 
    AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:[info objectForKey:@"UIImagePickerControllerReferenceURL"]] 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) { 

    } 
    UIImage *thumbImg = [[UIImage imageWithCGImage:im] retain]; 
    [generator release]; 
8

Je ne pouvais pas la solution de se réunir pour travailler pour moi, mais il m'a fait penser dans la bonne direction .

Ci-dessous le code que j'ai fini par utiliser dans mon projet. La méthode screenshotFromPlayer:maximumSize: accepte une instance d'un AVPlayer à partir de laquelle effectuer une capture d'écran et une CGSize qui correspond à la taille maximale de l'image renvoyée.

- (UIImage *)screenshotFromPlayer:(AVPlayer *)player maximumSize:(CGSize)maxSize { 

    CMTime actualTime; 
    NSError *error; 

    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:player.currentItem.asset]; 

    // Setting a maximum size is not necessary for this code to 
    // successfully get a screenshot, but it was useful for my project. 
    generator.maximumSize = maxSize; 

    CGImageRef cgIm = [generator copyCGImageAtTime:player.currentTime 
             actualTime:&actualTime 
              error:&error]; 
    UIImage *image = [UIImage imageWithCGImage:cgIm]; 
    CFRelease(cgIm); 

    if (nil != error) { 
     NSLog(@"Error making screenshot: %@", [error localizedDescription]); 
     NSLog(@"Actual screenshot time: %f Requested screenshot time: %f", CMTimeGetSeconds(actualTime), 
      CMTimeGetSeconds(self.recordPlayer.currentTime)); 
     return nil; 
    } 

    return image; 
} 

On notera également que l'on peut utiliser la méthode generateCGImagesAsynchronouslyForTimes:completionHandler: au lieu de copyCGImageAtTime:actualTime:error: (sur l'instance de AVAssetImageGenerator) pour effectuer la génération d'image de façon asynchrone.

Cet exemple de code génère une capture d'écran au currentTime, mais n'importe quel moment peut être utilisé à la place.

+2

Je sais que c'est super vieux mais pour tout le monde qui vient maintenant, assurez-vous que vous avez réellement un CGImageRef avant de le libérer. Si vous ne le faites pas, ce qui peut certainement arriver, l'application va planter. –

8

Le code pour obtenir l'image de avplayer.

- (UIImage *)currentItemScreenShot 
{ 
    AVPlayer *abovePlayer = [abovePlayerView player]; 
    CMTime time = [[abovePlayer currentItem] currentTime]; 
    AVAsset *asset = [[[abovePlayerView player] currentItem] asset]; 
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 
    if ([imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceBefore:)] && [imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceAfter:)]) { 
     [imageGenerator setRequestedTimeToleranceBefore:kCMTimeZero]; 
     [imageGenerator setRequestedTimeToleranceAfter:kCMTimeZero]; 
    } 
    CGImageRef imgRef = [imageGenerator copyCGImageAtTime:time 
              actualTime:NULL 
               error:NULL]; 
    if (imgRef == nil) { 
     if ([imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceBefore:)] && [imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceAfter:)]) { 
      [imageGenerator setRequestedTimeToleranceBefore:kCMTimePositiveInfinity]; 
      [imageGenerator setRequestedTimeToleranceAfter:kCMTimePositiveInfinity]; 
     } 
     imgRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL]; 
    } 
    UIImage *image = [[UIImage alloc] initWithCGImage:imgRef]; 
    CGImageRelease(imgRef); 
    [imageGenerator release]; 

    return [image autorelease]; 
} 

mis [imageGenerator setRequestedTimeToleranceBefore:kCMTimeZero] et [imageGenerator setRequestedTimeToleranceAfter:kCMTimeZero] si vous avez besoin de temps précis.