[英]AVAssetExportSession export fails with non-deterministic error
I'm trying to export videos with CIFilters applied using AVAssetExportSession, but sometimes it works and sometimes it doesn't.我正在尝试使用 AVAssetExportSession 应用 CIFilter 导出视频,但有时它可以工作,有时它不能。 It's unclear even how to reproduce the error.
甚至不清楚如何重现该错误。
I've noticed that there's no problem exporting videos recorded with an iPhone .我注意到导出用 iPhone 录制的视频没有问题。 But if I try to export a video downloaded from WhatsApp or a video I already exported before, I get the following error:
但是,如果我尝试导出从 WhatsApp 下载的视频或之前已经导出的视频,我会收到以下错误:
Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedFailureReason=The video could not be composed., NSLocalizedDescription=Operation Stopped, NSUnderlyingError=0x2839eaf10 {Error Domain=NSOSStatusErrorDomain Code=-17390 "(null)"}}
Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedFailureReason=无法合成视频。, NSLocalizedDescription=Operation Stopped, NSUnderlyingError=0x2839eaf10 {Error Domain=NSOSStatusErrorDomain Code=-17390 "(null)"}}
This is my code:这是我的代码:
var mutableComposition = AVMutableVideoComposition()
let exposureFilter = CIFilter.exposureAdjust()
func updateComposition() {
mutableComposition = AVMutableVideoComposition(asset: player.currentItem!.asset, applyingCIFiltersWithHandler: { request in
self.exposureFilter.inputImage = request.sourceImage.clampedToExtent()
self.exposureFilter.ev = 5
let output = self.exposureFilter.outputImage!.cropped(to: request.sourceImage.extent)
request.finish(with: output, context: nil)
})
player.currentItem?.videoComposition = mutableComposition
}
func exportVideo() {
let sourceAsset = AVURLAsset(url: videoURL)
let composition = AVMutableComposition()
let sourceVideoTrack = sourceAsset.tracks(withMediaType: .video)[0]
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
try? compositionVideoTrack!.insertTimeRange(CMTimeRangeMake(start: .zero, duration: sourceAsset.duration), of: sourceVideoTrack, at: .zero)
if sourceAsset.tracks(withMediaType: .audio).isEmpty == false {
// Video has sound
let sourceAudioTrack = sourceAsset.tracks(withMediaType: .audio)[0]
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
try? compositionAudioTrack!.insertTimeRange(CMTimeRangeMake(start: .zero, duration: sourceAsset.duration), of: sourceAudioTrack, at: .zero)
}
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
let videoID = UUID().uuidString
let videofileName = "\(videoID).mov"
let outputURL = documentsDirectory.appendingPathComponent(videofileName)
if FileManager.default.fileExists(atPath: outputURL.path) {
do {
try FileManager.default.removeItem(at: outputURL)
}
catch {}
}
let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)!
exporter.outputFileType = .mov
exporter.outputURL = outputURL
exporter.videoComposition = mutableComposition
exporter.exportAsynchronously(completionHandler: {
switch exporter.status {
case .failed:
print("Export failed \(exporter.error!)")
case .completed:
UISaveVideoAtPathToSavedPhotosAlbum(outputURL.path, self, #selector(video(_:didFinishSavingWithError:contextInfo:)), nil)
default:
break
}
}
}
Commenting out exporter.videoComposition = mutableComposition or changing the export preset to AVAssetExportPresetPassthrough fixes the error, but of course no CIFilters are applied to the video.注释掉exporter.videoComposition = mutableComposition或将导出预设更改为 AVAssetExportPresetPassthrough 可修复错误,但当然不会对视频应用 CIFilter。
So the problem seems to lie in the AVMutableVideoComposition.所以问题似乎在于 AVMutableVideoComposition。
I found a solution that worked for me.我找到了一个适合我的解决方案。
Replaced:替换:
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
With:和:
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: sourceVideoTrack.trackID)
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: sourceAudioTrack.trackID)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.