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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With