生产模式下导出合成视频时出现「Operation Stopped」错误求助
解决生产模式下AVAssetExportSession导出「Operation Stopped」错误
针对生产模式视频合成导出失败、开发模式正常的问题,以下是具体排查与修复方案:
1. 对齐合成时长与轨道实际时长
生产模式下视频asset的编码、加载可能存在细微差异,硬编码的runningTime易与合成轨道实际总时长不匹配,引发时间线冲突。
修复代码:
直接使用mixComposition.duration替代手动计算的runningTime:
// 音频插入时用合成的实际总时长 try musicAudioTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: mixComposition.duration), of: musicAudioTrackAsset, at: .zero) // 主指令时间范围同步为合成实际时长 mainInstruction.timeRange = CMTimeRangeMake(start: .zero, duration: mixComposition.duration)
2. 完善异常捕获与资源校验
当前代码空catch块会掩盖生产模式下的资源加载异常,且未校验音频轨道是否存在,直接导致导出静默失败。
修复代码:
let audioMix = AVMutableAudioMix() // 先校验音频轨道是否存在 guard let musicAudioTrackAsset = musicAsset.tracks(withMediaType: .audio).first else { // 处理无音频轨道的逻辑,比如跳过音轨添加 return } // 校验合成轨道添加是否成功 guard let musicAudioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { // 处理轨道添加失败逻辑 return } do { try musicAudioTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: mixComposition.duration), of: musicAudioTrackAsset, at: .zero) musicAudioTrack.preferredVolume = self.volumeSlider.value let audioMixInputParams = AVMutableAudioMixInputParameters() audioMixInputParams.trackID = musicAudioTrack.trackID audioMixInputParams.setVolume(self.volumeSlider.value, at: .zero) audioMix.inputParameters.append(audioMixInputParams) } catch { // 生产模式下收集错误日志,便于排查 print("音轨添加失败:\(error.localizedDescription)") }
3. 替换动态导出预设为具体分辨率
AVAssetExportPresetHighestQuality是动态预设,部分设备在生产模式下可能不支持对应编码格式,引发导出失败。
修复代码:
根据视频尺寸选择明确预设,并提前校验可用性:
let presetName = AVAssetExportPreset1920x1080 guard AVAssetExportSession.allExportPresets().contains(presetName) else { // 降级为可用预设,比如AVAssetExportPresetMediumQuality return } let exporter = AVAssetExportSession(asset: mixComposition, presetName: presetName)!
4. 校验视频层指令的时间范围合法性
每个videoLayerInstruction的操作时间点必须严格落在对应轨道的插入时间范围内,生产模式下超出范围会直接触发导出终止。
修复示例:
以片头视频层指令为例,确保时间范围与轨道插入范围一致:
// 片头在合成轨道中的插入时间范围 let frontTimeRange = CMTimeRangeMake(start: .zero, duration: frontAsset.duration) // 设置透明度动画时严格使用该时间范围 videoLayerInstructionFront.setOpacity(1.0, at: frontTimeRange.start) videoLayerInstructionFront.setOpacity(0.0, at: frontTimeRange.end) // 其他视频层指令同理,确保时间操作不超出各自轨道的插入范围
5. 确保输出路径的权限与可用性
生产模式下沙盒权限、文件已存在等问题会导致无法写入输出文件,触发导出错误。
修复代码:
let outputURL = self.template.finalURL // 校验路径是否在应用Documents目录内 guard outputURL.path.contains(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].path) else { return } // 若文件已存在,先删除旧文件 if FileManager.default.fileExists(atPath: outputURL.path) { try? FileManager.default.removeItem(at: outputURL) } exporter.outputURL = outputURL
6. 关闭网络优化选项
shouldOptimizeForNetworkUse会触发额外编码优化,生产模式下可能因性能或编码逻辑问题导致失败。
修复代码:
exporter.shouldOptimizeForNetworkUse = false
内容的提问来源于stack exchange,提问作者sarika scc
相关产品推荐
相关产品推荐

