Получить UIImage из CALayer, подключенного к AVPlayer (извлечь кадр из воспроизведения видео) - PullRequest
17 голосов
/ 28 ноября 2010

Я играю видео с AVPlayer.Это работает нормально.

Теперь я хочу получить UIImage из воспроизводимого видео (когда я нажимаю кнопку на данный момент).

Прикрепленный к моему AVPlayer есть CALayer, который используется для отображения видео на моем UIView.Моя идея - получить UIImage от CALayer во время воспроизведения видео.

Я делаю это с помощью кода из другого вопроса:

UIImage от CALayer - iPhone SDK

Однако мой UIImage пуст.Разрешение хорошее, но оно полностью белое !!!

Кажется, видео не записывает содержимое моего CALayer.

Кто-то может мне помочь?Спасибо

Ответы [ 3 ]

8 голосов
/ 14 сентября 2012

Я не мог заставить решение Meet работать на меня, но оно заставило меня задуматься в правильном направлении.

Ниже приведен код, который я использовал в своем проекте. Метод screenshotFromPlayer:maximumSize: принимает экземпляр AVPlayer, из которого делается снимок экрана, и CGSize, который будет максимальным размером возвращаемого изображения.

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

Также обратите внимание, что можно использовать метод generateCGImagesAsynchronouslyForTimes:completionHandler: вместо copyCGImageAtTime:actualTime:error: (в случае AVAssetImageGenerator) для асинхронной генерации изображения.

В этом примере кода создается снимок экрана AVPlayer currentTime, но вместо него можно использовать любое время.

8 голосов
/ 02 ноября 2012

Код для получения изображения от 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];
}

установите [imageGenerator setRequestedTimeToleranceBefore:kCMTimeZero] и [imageGenerator setRequestedTimeToleranceAfter:kCMTimeZero], если вам нужно точное время.

1 голос
/ 22 июня 2012

Попробуйте получить изображение из видеофайла в указанном экземпляре с помощью 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];
...