Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAssetImageGenerator fails at copying image

I am using AVAssetImageGenerator to create an image from the last frame of a video. This usually works fine, but every now and then copyCGImageAtTime fails with the error

NSLocalizedDescription = "Cannot Open";
NSLocalizedFailureReason = "This media cannot be used.";
NSUnderlyingError = "Error Domain=NSOSStatusErrorDomain Code=-12431";

I am verifying that the AVAsset is not nil and I'm pulling the CMTime directly from the asset, so I do not understand why this keeps happening. This only happens when trying to get the last frame, if I use kCMTimeZero instead, it seems to work.

- (void)getLastFrameFromAsset:(AVAsset *)asset completionHandler:(void (^)(UIImage *image))completion
{
    NSAssert(asset, @"Tried to generate last frame from nil asset");
    AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    gen.requestedTimeToleranceBefore = kCMTimeZero;
    gen.requestedTimeToleranceAfter = kCMTimeZero;
    gen.appliesPreferredTrackTransform = YES;
    CMTime time = [asset duration];
    NSError *error = nil;
    CMTime actualTime;

    CGImageRef imageRef = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
    UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
    NSAssert(image, @"Failed at generating image from asset's last frame");
    completion(image);
    CGImageRelease(imageRef);
}

This seems to be related, but it did not solve my problem.

like image 936
Daniel Larsson Avatar asked Oct 08 '16 17:10

Daniel Larsson


1 Answers

Nothing guarantees that your asset's video track exists at [asset duration]. It's duration can be shorter than the whole asset. Since you set the tolerance to kCMTimeZero the only possible resolution is failure.

Edit: To clarify, the issue emerges when you have an asset with audio track slightly longer than the video track.

like image 192
Artium Avatar answered Oct 26 '22 14:10

Artium