AVAssetImageGenerator在复制图像时失败

8

我正在使用AVAssetImageGenerator来从视频的最后一帧创建图像。这通常很好用,但是偶尔会发生copyCGImageAtTime失败的情况,错误信息如下:

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

我正在确认AVAsset不为空,并直接从媒体中提取CMTime,所以我不明白为什么这一直在发生。只有在尝试获取最后一帧时才会发生这种情况,如果我使用kCMTimeZero,似乎就可以工作了。

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

这个似乎与我的问题有关,但没有解决我的问题。


你有一部能够持续重现这个问题的电影文件吗? - Rhythmic Fistman
我在生成视频时只调用了这个方法一次。我使用它来通过冻结最后一帧几秒钟来扩展视频,然后使用AVMutableComposition生成新的视频。 - Daniel Larsson
似乎是太大的媒体文件。 - Nikita
1个回答

2

不能保证你的资产视频轨道存在于[资产持续时间]。它的持续时间可能比整个资产短。由于你将容差设置为kCMTimeZero,唯一可能的解决方案是失败。

编辑:澄清一下,当你有一个音频轨道略长于视频轨道的资产时,问题就会出现。


假设您的音频和视频时间不同,并且您正在使用 kCMTimeZero,那么您如何在设置的时间获取快照?或者如果您的音频比视频略长,该怎么办呢?在这种情况下应该采取什么解决方案? - impression7vx
@impression7vx 你需要访问资产的视频AVAssetTrack。可能会有多个,因此您需要决定哪一个(或选择第一个)。然后使用它的timeRange属性来查找它何时开始和结束。 https://developer.apple.com/documentation/avfoundation/avasset/1387140-trackswithmediatype?language=objc - Artium
1
有趣,太棒了。它在某种程度上起作用了;我做了类似于CMTime(seconds: audioTrackTime-videoTrackTime, preferredTimeScale: 600)的事情,但我仍然遇到错误,所以我做了CMTime(seconds: audioTrackTime-videoTrackTime+300, preferredTimeScale: 600)来给它一个半秒钟的缓冲区;它可以工作,但似乎非常不精确。 - impression7vx
@impression7vx 我不确定我理解了。为什么你要从视频轨道时间中减去音频轨道时间? - Artium
videoTrackTime 会给我一个 CMTime(seconds: 1250, preferredTimeScale: 600) 的持续时间,而 audioTrackTime 则是 CMTime(second: 1270, preferredTimeScale: 600),所以我会减去音频时间来确保如果音频在开头,视频对齐到结尾,那么视频将从 CMTime(seconds: 20, preferredTimeScale: 600) 开始。但是,这仍然不起作用,所以我添加了 0.5 秒的缓冲。 - impression7vx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接