AVAssetExportSession进入后台时暂停,如何实现后台持续导出?
让AVAssetExportSession在iOS后台持续运行的解决方案
我之前也碰到过一模一样的问题——iOS系统默认会在应用切到后台后很快挂起进程,直接打断AVAssetExportSession的导出流程。要解决这个问题,得结合后台权限配置和后台任务断言双管齐下,具体步骤如下:
1. 配置后台模式权限
首先得让系统知道你的应用在后台有媒体处理需求,开启对应的后台权限:
- 打开Xcode项目的
Signing & Capabilities面板,添加Background Modes能力 - 勾选
Audio, AirPlay, and Picture in Picture选项(AVAssetExportSession处理音频时,系统会基于这个权限允许后台持续运行相关任务) - 也可以直接在
Info.plist里手动添加UIBackgroundModes数组,加入audio字符串
2. 用后台任务断言延长后台运行时间
仅仅开了后台权限还不够,系统还是可能快速挂起应用,所以需要申请一个后台任务断言,让系统给应用额外的时间完成导出:
- 先定义一个变量保存后台任务标识符:
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid - 在启动导出任务前,申请后台任务:
// 申请后台任务,设置超时回调 backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "AudioMergeExport") { [weak self] in // 后台时间即将耗尽时,取消导出并清理 self?.assetExport?.cancel() UIApplication.shared.endBackgroundTask(self?.backgroundTaskID ?? .invalid) self?.backgroundTaskID = .invalid } - 然后初始化并启动你的导出任务:
self.assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) // 配置导出参数(输出URL、文件类型等) self.assetExport?.outputURL = yourTargetFileURL // 要指向沙盒可写目录,比如Documents self.assetExport?.outputFileType = .m4a self.assetExport?.exportAsynchronously(completionHandler: { [weak self] in defer { // 导出完成/失败/取消后,必须结束后台任务,避免被系统判定为违规 if let taskID = self?.backgroundTaskID, taskID != .invalid { UIApplication.shared.endBackgroundTask(taskID) self?.backgroundTaskID = .invalid } } // 处理导出结果 switch self?.assetExport?.status { case .completed: print("音频合并导出成功") case .failed: print("导出失败:\(self?.assetExport?.error?.localizedDescription ?? "未知错误")") case .cancelled: print("导出被取消") default: break } })
3. 额外注意事项
- 输出URL一定要指向应用沙盒内的可写目录(比如
Documents),别用临时目录,避免后台时文件被系统自动清理 - 优先使用
AVAssetExportPresetAppleM4A这类系统原生推荐的预设,部分自定义预设在后台可能存在兼容性问题 - 如果导出任务耗时超过10分钟,系统还是可能终止后台进程,这种极端场景可能需要考虑用
NSURLSession后台任务或者媒体处理扩展,但大多数音频合并场景,上面的方案已经足够
内容的提问来源于stack exchange,提问作者Chris Jones
相关产品推荐
相关产品推荐

