AVAssetExportSession AVFoundationErrorDomain代码-11800无法完成操作,在Swift iOS中NSOSStatusErrorDomain代码= -12780“(空)" [英] AVAssetExportSession AVFoundationErrorDomain Code -11800 The operation could not be completed, NSOSStatusErrorDomain Code=-12780 "(null) in Swift iOS

查看:365
本文介绍了AVAssetExportSession AVFoundationErrorDomain代码-11800无法完成操作,在Swift iOS中NSOSStatusErrorDomain代码= -12780“(空)"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Swift中开发一个基于视频的应用程序.我要在其中导出带有水印徽标和淡入淡出效果的视频剪辑.这是我的代码:

I am developing a Video based Application in Swift. Where I am exporting a Video clip with Watermark logo and Fade In Out effect. Here is my code:

func watermark(video videoAsset:AVAsset, videoModal:VideoModel, watermarkText text : String!, imageName name : String!, saveToLibrary flag : Bool, watermarkPosition position : PDWatermarkPosition, withMode mode: SpeedoVideoMode, completion : ((_ status : AVAssetExportSessionStatus?, _ session: AVAssetExportSession?, _ outputURL : URL?) -> ())?) {

        var arrayLayerInstructions:[AVMutableVideoCompositionLayerInstruction] = []
        let servicemodel = ServiceModel()

        DispatchQueue.global(qos: DispatchQoS.QoSClass.default).sync {

            let mixComposition = AVMutableComposition()

            let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))

            if videoAsset.tracks(withMediaType: AVMediaTypeVideo).count == 0

            {
                completion!(nil, nil, nil)
                return
            }

            let clipVideoTrack =  videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]

            self.addAudioTrack(composition: mixComposition, videoAsset: videoAsset as! AVURLAsset, withMode: mode, videoModal:videoModal)

            do {
                try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: clipVideoTrack, at: kCMTimeZero)

            }
            catch {
                print(error.localizedDescription)
            }

            let videoSize = clipVideoTrack.naturalSize //CGSize(width: 375, height: 300)

            //to add Watermark
            let parentLayer = CALayer()

            let videoLayer = CALayer()

            parentLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
            videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
            //videoLayer.backgroundColor = UIColor.red.cgColor
            parentLayer.addSublayer(videoLayer)

            if name != nil {
                let watermarkImage = UIImage(named: name)
                let imageLayer = CALayer()
                //imageLayer.backgroundColor = UIColor.purple.cgColor
                imageLayer.contents = watermarkImage?.cgImage

                var xPosition : CGFloat = 0.0
                var yPosition : CGFloat = 0.0
                let imageSize : CGFloat = 150

                switch (position) {
                case .TopLeft:
                    xPosition = 0
                    yPosition = 0
                    break
                case .TopRight:
                    xPosition = videoSize.width - imageSize - 100
                    yPosition = 80
                    break
                case .BottomLeft:
                    xPosition = 0
                    yPosition = videoSize.height - imageSize
                    break
                case .BottomRight, .Default:
                    xPosition = videoSize.width - imageSize
                    yPosition = videoSize.height - imageSize
                    break
                }

                imageLayer.frame = CGRect(x: xPosition, y: yPosition, width: imageSize, height: imageSize)
                imageLayer.opacity =  0.75
                parentLayer.addSublayer(imageLayer)

                if text != nil {
                    let titleLayer = CATextLayer()
                    titleLayer.backgroundColor = UIColor.clear.cgColor
                    titleLayer.string = text
                    titleLayer.font = "Helvetica" as CFTypeRef
                    titleLayer.fontSize = 20
                    titleLayer.alignmentMode = kCAAlignmentRight
                    titleLayer.frame = CGRect(x: 0, y: yPosition - imageSize, width: videoSize.width - imageSize/2 - 4, height: 57)
                    titleLayer.foregroundColor = UIColor.lightGray.cgColor
                    parentLayer.addSublayer(titleLayer)
                }
            }

            let videoComp = AVMutableVideoComposition()
            videoComp.renderSize = videoSize
            videoComp.frameDuration = CMTimeMake(1, 30)
            videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)


            let instruction = AVMutableVideoCompositionInstruction()
            instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)

            _ = mixComposition.tracks(withMediaType: AVMediaTypeVideo)[0] as AVAssetTrack

            let layerInstruction = self.videoCompositionInstructionForTrack(track: compositionVideoTrack, asset: videoAsset)

            //Add Fade In Out effects
            let startTime = CMTime(seconds: Double(0), preferredTimescale: 1000)
            let endTime = CMTime(seconds: Double(1), preferredTimescale: 1000)
            let timeRange = CMTimeRange(start: startTime, end: endTime)
            layerInstruction.setOpacityRamp(fromStartOpacity: 0.1, toEndOpacity: 1.0, timeRange: timeRange)

            let startTime1 = CMTime(seconds: videoAsset.duration.seconds-1, preferredTimescale: 1000)
            let endTime1 = CMTime(seconds: videoAsset.duration.seconds, preferredTimescale: 1000)
            let timeRange1 = CMTimeRange(start: startTime1, end: endTime1)
            layerInstruction.setOpacityRamp(fromStartOpacity: 1.0, toEndOpacity: 0.1, timeRange: timeRange1)

            arrayLayerInstructions.append(layerInstruction)

            instruction.layerInstructions = arrayLayerInstructions
            videoComp.instructions = [instruction]

            let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]

            let url = URL(fileURLWithPath: documentDirectory).appendingPathComponent("\(videoModal.fileID).mov")

            let filePath = url.path
            let fileManager = FileManager.default

            do {
                if fileManager.fileExists(atPath: filePath) {
                    print("FILE AVAILABLE")

                    try fileManager.removeItem(atPath:filePath)
                } else {
                    print("FILE NOT AVAILABLE")
                }
            } catch _ {
            }

            let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
            exporter?.outputURL = url
            exporter?.outputFileType = AVFileTypeQuickTimeMovie

            let timeRangetoTrim = CMTimeRange(start: CMTime(seconds: Double(videoModal.leftRangeValue), preferredTimescale: 1000),
                                              end: CMTime(seconds: Double(videoModal.rightRangeValue), preferredTimescale: 1000))

            exporter?.timeRange = timeRangetoTrim

            exporter?.shouldOptimizeForNetworkUse = false
            exporter?.videoComposition = videoComp

            exporter?.exportAsynchronously() {
                DispatchQueue.main.async {

                    if exporter?.status == AVAssetExportSessionStatus.completed {

                        let outputURL = exporter?.outputURL
                        if flag {
                            if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL!.path) {
                                PHPhotoLibrary.shared().performChanges({
                                    PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputURL!)
                                }) { saved, error in
                                    if saved {
                                        completion!(AVAssetExportSessionStatus.completed, exporter, outputURL)
                                    }
                                }
                            }

                        } else {
                            completion!(AVAssetExportSessionStatus.completed, exporter, outputURL)
                        }

                    } else {
                        // Error
                        completion!(exporter?.status, exporter, nil)// Getting error here
                    }
                }
            }
        }
    }


func addAudioTrack(composition: AVMutableComposition, videoAsset: AVURLAsset, withMode mode: SpeedoVideoMode, videoModal:VideoFileModel) {

        let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
        let audioTracks = videoAsset.tracks(withMediaType: AVMediaTypeAudio)
        for audioTrack in audioTracks {
            try! compositionAudioTrack.insertTimeRange(audioTrack.timeRange, of: audioTrack, at: kCMTimeZero)
        }
    }

func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {
        let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
        let assetTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]

        let transform = assetTrack.preferredTransform
        let assetInfo = orientationFromTransform(transform: transform)

        var scaleToFitRatio = UIScreen.main.bounds.width / 375
        if assetInfo.isPortrait {
            scaleToFitRatio = UIScreen.main.bounds.width / assetTrack.naturalSize.height
            let scaleFactor = CGAffineTransform(scaleX: scaleToFitRatio, y: scaleToFitRatio)
            instruction.setTransform(assetTrack.preferredTransform.concatenating(scaleFactor),
                                     at: kCMTimeZero)
        } else {
            let scaleFactor = CGAffineTransform(scaleX: scaleToFitRatio, y: scaleToFitRatio)
            var concat = assetTrack.preferredTransform.concatenating(scaleFactor).concatenating(CGAffineTransform(translationX: 0, y: 0))
            if assetInfo.orientation == .down {
                let fixUpsideDown = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
                let windowBounds = UIScreen.main.bounds
                let yFix = 375 + windowBounds.height
                let centerFix = CGAffineTransform(translationX: assetTrack.naturalSize.width, y: CGFloat(yFix))
                concat = fixUpsideDown.concatenating(centerFix).concatenating(scaleFactor)
            }
            instruction.setTransform(concat, at: kCMTimeZero)

        }

        return instruction
    }


private func orientationFromTransform(transform: CGAffineTransform) -> (orientation: UIImageOrientation, isPortrait: Bool) {
        var assetOrientation = UIImageOrientation.up
        var isPortrait = false
        if transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0 {
            assetOrientation = .right
            isPortrait = true
        } else if transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0 {
            assetOrientation = .left
            isPortrait = true
        } else if transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0 {
            assetOrientation = .up
        } else if transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0 {
            assetOrientation = .down
        }

        return (assetOrientation, isPortrait)
    }

我的代码在某些视频中工作正常,有时对某些视频也不起作用.由于AVAssetExportSessionStatus失败,我遇到以下错误:

My code is working fine for some of the videos and sometimes it's not working for some videos too. I am getting below error due to AVAssetExportSessionStatus failed :

Error Domain = AVFoundationErrorDomain代码= -11800该操作可能 未完成" UserInfo = {NSLocalizedFailureReason =未知错误 发生(-12780),NSLocalizedDescription =无法执行该操作 已完成,NSUnderlyingError = 0x28262c240 {Error Domain = NSOSStatusErrorDomain Code = -12780(null)"}}

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x28262c240 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}}

有人可以帮我吗?预先谢谢你.

Can anyone help me on this? Thank you in advance.

推荐答案

此方法func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {是错误的,因为您需要提供AVAssetTrack并包含实际视频.

This method func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction { is wrong because you need to provide and AVAssetTrack which has the actual videos.

但是,您要传递的仍然是AVCompositionTrack,因此请使用此func videoCompositionInstructionForTrack(track: AVAssetTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {替换您的方法.

But instead of that, you are passing AVCompositionTrack which is still need to be composed, so replace your method with this func videoCompositionInstructionForTrack(track: AVAssetTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {.

现在,当您调用实际方法时,需要传递clipVideoTrack,即let layerInstruction = self.videoCompositionInstructionForTrack(track: clipVideoTrack, asset: videoAsset).

Now when you are calling the actual method, you need to pass clipVideoTrack, i.e., let layerInstruction = self.videoCompositionInstructionForTrack(track: clipVideoTrack, asset: videoAsset).

如果您仍然遇到错误,请告诉我!

let me know, if you are still facing the error!

这篇关于AVAssetExportSession AVFoundationErrorDomain代码-11800无法完成操作,在Swift iOS中NSOSStatusErrorDomain代码= -12780“(空)"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆