首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVAssetExportSession停止运行

AVAssetExportSession停止运行
EN

Stack Overflow用户
提问于 2012-05-24 04:43:15
回答 4查看 4.6K关注 0票数 17

我在AVAssetExportSession上遇到了一个问题,进程停止增加,但状态仍然显示它正在导出。这实际上是一个相当罕见的情况,它在99.99%的时间内都能完美地工作,但我还是想解决这个问题。

所以我开始导出:

代码语言:javascript
复制
    exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
    exportSession.videoComposition = videoComposition; 
    exportSession.outputFileType = @"com.apple.quicktime-movie";
    exportSession.outputURL = outputURL;
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        ...
    }];

然后使用计时器检查进度:

代码语言:javascript
复制
    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];

输出结果如下所示:

代码语言:javascript
复制
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

(注意:它并不是每次都以相同的百分比停止,它完全是随机的)

正如你从时间戳中看到的,它花了5秒完成前88%,然后我让它再运行13分钟(完整的视频处理通常不会超过10秒),进度没有变化。

目前,我唯一的选择是检查进度是否在过去X秒内没有改变,然后告诉用户失败,然后重试。

有谁有什么想法吗?

EN

回答 4

Stack Overflow用户

发布于 2014-02-10 11:29:51

在我的例子中,这个问题源于使用不寻常的配置编码的mp4s。但最终导致这个问题的是苹果代码中的一个bug。

具体地说,我在Facebook上和mp4s一起工作。似乎facebook在对视频进行编码时,会丢弃或移动视频轨道的第一帧。使用ffprobe查看视频显示:

代码语言:javascript
复制
        "r_frame_rate": "722/25",
        "avg_frame_rate": "722/25",
        "time_base": "1/28880",
        "start_pts": 1000,
        "start_time": "0.034626",

不幸的是,苹果的API不能正确地报告曲目的开始时间。在从AVAsset获取AVAssetTrack并检查其timeRange之后,它报告开始时间为0。我可能误解了赛道和资产计时的本质,但这似乎是一个错误。

当然,在为导出会话构建视频合成时,我使用了不正确的跟踪时间范围。我怀疑,当导出会话在时间0查找磁道中的数据时,它会感到困惑,然后就像我们看到的那样,只是挂起,甚至没有报告错误-另一个错误。即使使用videoCompositionWithPropertiesOfAsset:创建组合也没有帮助。

我还没有尝试使用AVAssetReader和AVAssetWriter来代替AVAssetExportSession,所以我不知道您是否会遇到同样的情况。直到我有更多的时间来探索,我已经想出了这个hack作为解决方案:

将用于曲目插入和视频指令的时间范围重置为从1帧或2帧开始:

代码语言:javascript
复制
CMTimeRange videoTimeRange = videoTrack.timeRange;
videoTimeRange.start = CMTimeMake(1, ceil(videoTrack.nominalFrameRate));

显然,该hack仅适用于视频轨道开始时间不为0的特定情况。我猜测,一般来说,这个bug是由AVAssetExportSession及其相关类所不期望的不寻常的媒体编码引起的。

票数 4
EN

Stack Overflow用户

发布于 2013-02-18 04:47:06

我已经找到了!

您需要设置正确的layerInstructions:

代码语言:javascript
复制
AVMutableCompositionTrack *track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];


AVMutableVideoCompositionLayerInstruction * layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:track];


AVMutableVideoCompositionInstruction * MainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
MainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, allTime);
MainInstruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];

否则它就会卡住。

票数 3
EN

Stack Overflow用户

发布于 2013-02-23 13:46:06

我想知道这是不是线程的问题-如果计时器和导出器在不同的线程中结束。( AVFoundation指南指出,不能保证导出器在任何特定线程上运行。)

您是否尝试过使用键值观察而不是计时器?

基本框架示例:

代码语言:javascript
复制
// register for the notification
[exportSession addObserver:someProcessor forKeyPath:@"progress" options:NSKeyValueObservingOptionNew context:NULL];

然后在你的处理器中:

代码语言:javascript
复制
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    // add some checks here
    NSNumber *processNumber = [change objectForKey:NSKeyValueChangeNewKey];
    float process = [processNumber floatValue];
    [delegate processor:self didProgress:progress];
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10727530

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档