Daniel Larsson
Daniel Larsson

Reputation: 6394

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.

Upvotes: 8

Views: 2335

Answers (1)

Artium
Artium

Reputation: 5329

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.

Upvotes: 2

Related Questions