iOS中AVAssetExportSession裁剪视频后Network发送未生效问题排查
问题排查与解决
核心问题1:裁剪起始时间未正确赋值
在autoTrimBeforeSending函数中,你计算了startTimeSec = videoDurationInSeconds - VideoConstants.autoTrimSec(即取最后4秒),但这个计算后的值并没有被用来创建startCMTime,你依然使用了初始的startTimeSec = 0.0生成起始时间,导致裁剪范围还是从视频开头到结尾,等于没有执行有效裁剪。
修改后的autoTrimBeforeSending代码:
func autoTrimBeforeSending(completion: @escaping () -> Void) { let options: [String : Any] = [AVURLAssetPreferPreciseDurationAndTimingKey: false] let videoURLAsset = AVURLAsset(url: theVideoURL, options: options) let videoDurationInSeconds = videoURLAsset.duration.seconds // 直接计算目标起始时间 let startTimeSec = videoDurationInSeconds - VideoConstants.autoTrimSec // 取最后4秒 // 用计算后的起始时间创建CMTime let startCMTime = CMTimeMakeWithSeconds(startTimeSec, preferredTimescale: 600) let composition = AVMutableVideoComposition(propertiesOf: videoURLAsset) let endTime = CMTimeMakeWithSeconds(videoDurationInSeconds, preferredTimescale: 600) VideoUtils.export(videoURLAsset, to: theVideoURL, startTime: startCMTime, endTime: endTime, composition: composition, completion: { _ in completion() }) }
核心问题2:输入输出URL相同可能引发异常
你将导出的输出URL设置为原视频的URL(theVideoURL),虽然代码中先尝试删除旧文件,但如果原视频文件此时正被AVURLAsset持有引用,可能会导致删除失败或者导出过程中出现文件占用问题,最终导出失败但你未处理completion的false状态,直接执行了发送逻辑。
建议改为使用临时文件URL作为输出,示例:
func autoTrimBeforeSending(completion: @escaping () -> Void) { let options: [String : Any] = [AVURLAssetPreferPreciseDurationAndTimingKey: false] let videoURLAsset = AVURLAsset(url: theVideoURL, options: options) let videoDurationInSeconds = videoURLAsset.duration.seconds let startTimeSec = videoDurationInSeconds - VideoConstants.autoTrimSec let startCMTime = CMTimeMakeWithSeconds(startTimeSec, preferredTimescale: 600) let composition = AVMutableVideoComposition(propertiesOf: videoURLAsset) let endTime = CMTimeMakeWithSeconds(videoDurationInSeconds, preferredTimescale: 600) // 生成临时输出URL let tempDir = FileManager.default.temporaryDirectory let tempOutputURL = tempDir.appendingPathComponent("trimmed_video_\(UUID().uuidString).mov") VideoUtils.export(videoURLAsset, to: tempOutputURL, startTime: startCMTime, endTime: endTime, composition: composition, completion: { success in if success { networkSession.sendVideo(from: tempOutputURL) // 发送完成后清理临时文件 try? FileManager.default.removeItem(at: tempOutputURL) } else { // 处理导出失败逻辑,比如提示用户 } completion() }) }
额外注意:处理导出失败的情况
当前代码中忽略了export回调的失败状态,直接调用completion(),这会导致即使导出失败,依然执行发送原视频的逻辑。建议根据success状态决定是否继续发送,避免发送未裁剪的原视频。
内容的提问来源于stack exchange,提问作者cleanrun
相关产品推荐
相关产品推荐

