![](/img/trans.png)
[英]AVAssetExportSession export fails non-deterministically with error: "Operation Stopped, NSLocalizedFailureReason=The video could not be composed."
[英]AVAssetExportSession export fails with non-deterministic error
我正在尝试使用 AVAssetExportSession 应用 CIFilter 导出视频,但有时它可以工作,有时它不能。 甚至不清楚如何重现该错误。
我注意到导出用 iPhone 录制的视频没有问题。 但是,如果我尝试导出从 WhatsApp 下载的视频或之前已经导出的视频,我会收到以下错误:
Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedFailureReason=无法合成视频。, NSLocalizedDescription=Operation Stopped, NSUnderlyingError=0x2839eaf10 {Error Domain=NSOSStatusErrorDomain Code=-17390 "(null)"}}
这是我的代码:
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
}
}
}
注释掉exporter.videoComposition = mutableComposition或将导出预设更改为 AVAssetExportPresetPassthrough 可修复错误,但当然不会对视频应用 CIFilter。
所以问题似乎在于 AVMutableVideoComposition。
我找到了一个适合我的解决方案。
替换:
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
和:
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.