You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 16下使用AVFoundation导出视频完成后应用卡顿问题

解决方案:iOS 16下AVAssetExportSession加animationTool导致UI冻结问题

根据你提供的调用栈,主线程卡在Core Animation事务提交阶段,这说明导出完成后animationTool相关的Core Animation资源没有正确处理,导致主线程阻塞。以下是几个可行的修复方案:


1. 导出完成后强制清理animationTool并刷新CATransaction

在导出完成的回调中,先清空AVVideoComposition的animationTool引用,然后手动触发CATransaction刷新,确保所有pending的动画事务都被处理,避免主线程阻塞:

// Objective-C示例
[exportSession exportAsynchronouslyWithCompletionHandler:^{
    // 处理导出结果(成功/失败)
    dispatch_async(dispatch_get_main_queue(), ^{
        // 清空animationTool引用
        self.videoComposition.animationTool = nil;
        // 强制刷新CATransaction
        [CATransaction flush];
        
        // 后续的UI更新操作放在这里
    });
}];
// Swift示例
exportSession.exportAsynchronously { [weak self] in
    // 处理导出结果
    DispatchQueue.main.async {
        self?.videoComposition?.animationTool = nil
        CATransaction.flush()
        
        // 执行UI更新
    }
}

2. 严格区分Core Animation操作与导出操作的线程

AVVideoCompositionCoreAnimationTool依赖Core Animation的layer对象,这类对象是线程绑定的,必须在主线程完成初始化、绑定到videoComposition的操作;仅将导出任务本身放在后台队列执行:

// 主线程创建并绑定animationTool
AVVideoCompositionCoreAnimationTool *animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
self.videoComposition.animationTool = animationTool;

// 后台队列执行导出逻辑
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:self.asset presetName:AVAssetExportPresetHighestQuality];
    exportSession.videoComposition = self.videoComposition;
    // 设置其他导出参数(输出路径、文件类型等)
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        // 后续处理同方案1
    }];
});

3. 替换AVAssetExportSession为AVAssetWriter(彻底规避系统bug)

如果上述方案仍无法解决问题,大概率是iOS 16中AVAssetExportSession与animationTool组合存在系统级bug。此时可以改用更底层的AVAssetWriter实现导出,完全自主控制合成流程:

  1. 创建AVAssetWriter及对应的AVAssetWriterInput
  2. 创建绑定好animationTool的AVVideoComposition
  3. 使用AVAssetReader读取源视频数据,配合AVVideoCompositionRenderContext将带动画的帧写入AVAssetWriter

这种方式代码量更大,但能彻底避开AVAssetExportSession的潜在问题,稳定性更高。


4. 导出完成后触发主线程RunLoop处理未完成事件

如果主线程卡在RunLoop等待事务,可以在回调中手动触发RunLoop处理当前pending事件:

dispatch_async(dispatch_get_main_queue(), ^{
    self.videoComposition.animationTool = nil;
    // 让主线程RunLoop处理完所有待执行事件
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
});

内容的提问来源于stack exchange,提问作者Rafi Martirosyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:10:36