简体   繁体   English

AVAssetExportSession 导出失败并出现非确定性错误

[英]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.

相关问题 AVAssetExportSession 导出不确定性地失败并显示错误:“操作已停止,NSLocalizedFailureReason=无法制作视频。” - AVAssetExportSession export fails non-deterministically with error: "Operation Stopped, NSLocalizedFailureReason=The video could not be composed." AVAssetExportSession导出需要很多时间 - AVAssetExportSession export takes a lot of time AVAssetExportSession 未开始导出/卡在等待中 - AVAssetExportSession not starting export / stuck waiting 使用 AVAssetExportSession Swift 导出 MP4 - Swift Export MP4 using AVAssetExportSession 通过 AVAssetExportSession 导出 mp4 失败 - Exporting mp4 through AVAssetExportSession fails AVAssetExportSession 导出失败 NSURLErrorDomain Code-=3000 (Swift) - AVAssetExportSession export failure NSURLErrorDomain Code-=3000 (Swift) AVAssetExportSession无法从照片库转换.mov。为什么? - AVAssetExportSession fails to convert .mov from photo library. Why? AVAssetExportSession 在 IOS 13 上失败,将音频和视频混合在一起 - AVAssetExportSession fails on IOS 13, muxing together audio and video 将 AVAsset 导出到临时 iOS 路径时,AVAssetExportSession 抛出错误 - AVAssetExportSession throws error when exporting AVAsset to temporary iOS path AVAssetExportSession第一次起作用,但是如果我再试一次则失败-无法组成视频 - AVAssetExportSession works the first time but fails if I try again - The video could not be composed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM