Avassetexportsession导出失败,不确定性错误

发布于 2025-02-11 14:15:40 字数 3253 浏览 0 评论 0原文

我正在尝试使用使用Avassetexportsession应用的Cifilter导出视频,但是有时它有效,有时行不通。目前尚不清楚如何重现错误。

我注意到用iPhone 导出视频没有问题。但是,如果我尝试导出从WhatsApp下载或以前已经导出的视频下载的视频,我会收到以下错误:

错误域= avFoundationRordomain代码= -11841“操作停止” USERINFO = {NSlocalizedFailureReason =无法组成视频。 nslocalizedDescription =操作停止, nsunderlyingerror = 0x2839EAF10 {错误域= nsosstatusorrordomain 代码= -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.videOporter.videOporter = mutableComposition 或将导出预设更改为avassetexportpresetpassthrough file fime avaseTectprestthrough files files of files视频。

因此,这个问题似乎在于avmutable Videopomposition。

I'm trying to export videos with CIFilters applied using AVAssetExportSession, but sometimes it works and sometimes it doesn't. It's unclear even how to reproduce the error.

I've noticed that there's no problem exporting videos recorded with an iPhone. But if I try to export a video downloaded from WhatsApp or a video I already exported before, I get the following error:

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)"}}

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.

So the problem seems to lie in the AVMutableVideoComposition.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏花。依旧 2025-02-18 14:15:41

我找到了一种对我有用的解决方案。

替换:

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)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文