AVAssetExportSession导出太慢

时间:2015-07-24 12:06:27

标签: ios objective-c video avfoundation avassetexportsession

我正在尝试使用AVMutableComposition导出AVAssetExportSession

AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL=url;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    exporter.videoComposition = mainCompositionInst;
    exporter.shouldOptimizeForNetworkUse = YES;

    [exporter exportAsynchronouslyWithCompletionHandler:^
     {
         switch (exporter.status)
         {
             case AVAssetExportSessionStatusCompleted:
             {
                 NSLog(@"Video Merge SuccessFullt");
             }
                 break;
             case AVAssetExportSessionStatusFailed:
                 NSLog(@"Failed:%@", exporter.error.description);
                 break;
             case AVAssetExportSessionStatusCancelled:
                 NSLog(@"Canceled:%@", exporter.error);
                 break;
             case AVAssetExportSessionStatusExporting:
                 NSLog(@"Exporting!");
                 break;
             case AVAssetExportSessionStatusWaiting:
                 NSLog(@"Waiting");
                 break;
             default:
                 break;
         }
     }];

但是出口即使是1分钟的视频也需要大约30秒,考虑到iPad内置的相机应用只需不到2秒,这太过分了。

此外,如果我从导出器中删除videoComposition,则时间减少到7秒,考虑到视频长度仅为1分钟,这仍然很糟糕。 那么,我想知道如何将出口时间减少到最低限度?

另外,我想知道,AVAssetExportSession一般花费这么多时间还是仅仅是我的情况?

更新: 合并代码:

AVMutableComposition * mutableComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *videoCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                                   preferredTrackID:kCMPersistentTrackID_Invalid];

AVMutableCompositionTrack *audioCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                                   preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableVideoCompositionLayerInstruction *videoTrackLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoCompositionTrack];


NSMutableArray *instructions = [NSMutableArray new];
CGSize size = CGSizeZero;

CMTime time = kCMTimeZero;
for (AVURLAsset *asset in assets)
{
    AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVAssetTrack *audioAssetTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;



    NSError *error;
    [videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, assetTrack.timeRange.duration )
                                       ofTrack:assetTrack
                                        atTime:time
                                         error:&error];

    [videoTrackLayerInstruction setTransform:assetTrack.preferredTransform atTime:time];

    if (error) {
        NSLog(@"asset url :: %@",assetTrack.asset);
        NSLog(@"Error1 - %@", error.debugDescription);
    }

    [audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAssetTrack.timeRange.duration)
                                       ofTrack:audioAssetTrack
                                        atTime:time
                                         error:&error];
    if (error) {
        NSLog(@"Error2 - %@", error.debugDescription);
    }

    time = CMTimeAdd(time, assetTrack.timeRange.duration);

    if (CGSizeEqualToSize(size, CGSizeZero)) {
        size = assetTrack.naturalSize;
    }
}

AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, time);
mainInstruction.layerInstructions = [NSArray arrayWithObject:videoTrackLayerInstruction];
AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);
mainCompositionInst.renderSize = size;

3 个答案:

答案 0 :(得分:2)

我认为这里的问题是AVAssetExportPresetHighestQuality,这将导致转换或上采样,并且会降低传输速度。尝试改用AVAssetExportPresetPassthrough。我的导出时间从〜35 +秒降低到不到一秒钟

我还禁用了针对网络使用的优化功能,因为我们所有的视频都仅在应用内使用,并且从未通过网络流式传输或传递

答案 1 :(得分:1)

我构建了一个将不同视频片段合并在一起的应用程序,我可以肯定地说这是你的情况。我的视频文件大约有10 MB,所以它们可能会小一些,但将它们合并在一起所需的时间不到一秒,即使有10个,20个段也是如此。

现在至于它实际上正在发生,我已经检查了我的配置与你的配置,差异在于:

  • 我使用export.outputFileType = AVFileTypeMPEG4
  • 我已禁用网络优化,如果您不打算从设备中流式传输视频,则应禁用它

除此之外,它应该是相同的,我无法真正比​​较它,因为你必须提供有关如何实际创建合成的代码。有些事情要检查:

  • 如果您在创建AVURLAssetPreferPreciseDurationAndTimingKey时使用AVURLAsset并且没有足够的关键帧,实际上可能需要相当长的时间才能找到密钥,因此会降低速度
  • 考虑一下您是否真的需要最高质量的视频
  • 考虑视频的分辨率并可能降低视频

如果您提供更多信息,我应该能够为您提供更多帮助,但也许其中一些可行。试一试然后报告。

希望它有所帮助!

编辑1: 我忘了提到如果你没有选择,你应该尝试使用FFmpeg库,因为它的性能非常高,但由于许可可能不适合你。

答案 2 :(得分:0)

请记住,您尝试导出的资产可能不是本地存储的,首先是下载内容,然后导出您的资产。

如果您不想下载任何内容

let videoRequestOptions: PHVideoRequestOptions = PHVideoRequestOptions()
videoRequestOptions.isNetworkAccessAllowed = true

您还将在requestExportSession完成处理程序中收到一条消息,其中包含几个有用的信息值。 https://developer.apple.com/documentation/photokit/phimagemanager/image_result_info_keys

否则,如果您想从iCloud下载资产并使其尽快运行,则可以使用以下参数

let videoRequestOptions: PHVideoRequestOptions = PHVideoRequestOptions()
// highQualityFormat, highQualityFormat, fastFormat, automatic
videoRequestOptions.deliveryMode = .fastFormat 
videoRequestOptions.isNetworkAccessAllowed = true

另一个重要属性是导出预设,有一堆可用的预设

let lowQualityPreset1 = AVAssetExportPresetLowQuality
let lowQualityPreset2 = AVAssetExportPreset640x480
let lowQualityPreset3 = AVAssetExportPreset960x540
let lowQualityPreset4 = AVAssetExportPreset1280x720

let manager = PHImageManager()
manager.requestExportSession(forVideo: asset, 
                              options: videoRequestOptions, 
                         exportPreset: lowQualityPreset1) { (session, info) in
  session?.outputURL = outputUrl
  session?.outputFileType = .mp4
  session?.shouldOptimizeForNetworkUse = true

  session?.exportAsynchronously {

  }
}