我在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及其相关类所期望的异常媒体编码引起的。

09-11 20:17