我在AVAssetExportSession中遇到问题,进度停止增加,但状态仍然表明它正在导出。这实际上是一种非常罕见的情况,它在99.99%的时间内都能正常工作,但是无论如何我都想解决此问题。
因此,我开始导出:
exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
exportSession.videoComposition = videoComposition;
exportSession.outputFileType = @"com.apple.quicktime-movie";
exportSession.outputURL = outputURL;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
...
}];
然后让计时器检查进度:
AVAssetExportSessionStatus status = [exportSession status];
float progress = 0;
if (status == AVAssetExportSessionStatusExporting) {
progress = [exportSession progress];
} else if (status == AVAssetExportSessionStatusCompleted) {
progress = 1;
}
NSLog(@"%d %f", status, progress);
[delegate processor:self didProgress:progress];
输出最终看起来像:
2012-05-23 14:28:59.494 **********[1899:707] 2 0.125991
2012-05-23 14:28:59.994 **********[1899:707] 2 0.185280
2012-05-23 14:29:00.494 **********[1899:707] 2 0.259393
2012-05-23 14:29:00.994 **********[1899:707] 2 0.326093
2012-05-23 14:29:01.494 **********[1899:707] 2 0.400206
2012-05-23 14:29:01.995 **********[1899:707] 2 0.481729
2012-05-23 14:29:02.495 **********[1899:707] 2 0.541019
2012-05-23 14:29:02.997 **********[1899:707] 2 0.622542
2012-05-23 14:29:03.493 **********[1899:707] 2 0.681832
2012-05-23 14:29:03.995 **********[1899:707] 2 0.763355
2012-05-23 14:29:04.494 **********[1899:707] 2 0.822645
2012-05-23 14:29:04.994 **********[1899:707] 2 0.880082
2012-05-23 14:29:05.493 **********[1899:707] 2 0.880082
2012-05-23 14:29:05.994 **********[1899:707] 2 0.880082
...
2012-05-23 14:43:22.994 **********[1899:707] 2 0.880082
2012-05-23 14:43:23.493 **********[1899:707] 2 0.880082
2012-05-23 14:43:23.994 **********[1899:707] 2 0.880082
2012-05-23 14:43:24.494 **********[1899:707] 2 0.880082
(注意:它不会每次都以相同的百分比停下来,完全是随机的)
从时间戳中可以看到,前88%的内容花了5秒钟,然后我又让它运行了13分钟(完整的视频处理通常不会花10秒钟以上),而且进度没有变化。
目前,我唯一的选择是检查进度在最近X秒钟内是否没有改变,只是告诉用户失败了,然后重试。
有人有想法么?
最佳答案
以我为例,此问题源于以异常配置编码的mp4。但是最终苹果代码中的错误导致了问题。
具体来说,我当时在Facebook上使用mp4。看来,当Facebook对视频进行编码时,它会掉落或移动视频轨道的第一帧。用ffprobe检查视频显示:
"r_frame_rate": "722/25",
"avg_frame_rate": "722/25",
"time_base": "1/28880",
"start_pts": 1000,
"start_time": "0.034626",
0.034626恰好是帧2的时间。但是,音轨从0开始。
不幸的是,Apple的API无法正确报告该轨道的开始时间。从AVAsset获取AVAssetTrack并检查其timeRange后,它报告开始时间为0。可能我误解了轨道和 Assets 计时的本质,但这似乎是一个错误。
当然,在为导出 session 构建视频作品时,我使用了不正确的跟踪时间范围。我怀疑当导出 session 在时间0处在轨道中查找数据并且什么也没发现时会感到困惑,然后如我们所见,只是挂起,甚至没有报告错误-另一个错误。即使使用videoCompositionWithPropertiesOfAsset:创建合成也无济于事。
我尚未尝试使用AVAssetReader和AVAssetWriter而不是AVAssetExportSession,所以我不知道您是否会在那遇到相同的情况。在没有更多时间探索之前,我已经提出了此hack作为解决方案:
将用于轨道插入和视频指示的时间范围重置为从1帧或2帧开始:
CMTimeRange videoTimeRange = videoTrack.timeRange;
videoTimeRange.start = CMTimeMake(1, ceil(videoTrack.nominalFrameRate));
显然,这种破解仅适用于视频轨道开始时间不为0的特定情况。我猜想,此错误通常是由AVAssetExportSession及其相关类所期望的异常媒体编码引起的。