如何使用AVMutableComposition

时间:2019-12-24 02:16:38

标签: ios swift video avfoundation avmutablecomposition

我正在尝试开发一个具有类似于Snapchat或Instagram的照片编辑功能的应用程序。我正在使用giphy,以便用户可以向照片添加动画贴纸/图像,但是我不知道如何导出它们。到目前为止,我能够导出静态图像,但不能导出任何动画gif。我可以将giphy图像转换为mp4格式,但是我仍然不知道如何将其覆盖在视频上。如果有人帮助我,我将非常感激。

这里有导出静止编辑的功能,我对AVFoundation不太满意,而且我在网上搜索解决方案,也没有运气。

func convertVideoAndSaveTophotoLibrary(videoURL: URL) {
    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let myDocumentPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4").absoluteString
    _ = NSURL(fileURLWithPath: myDocumentPath)
    let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
    let filePath = documentsDirectory2.appendingPathComponent("video.mp4")
    deleteFile(filePath: filePath as NSURL)

    //Check if the file already exists then remove the previous file
    if FileManager.default.fileExists(atPath: myDocumentPath) {
        do { try FileManager.default.removeItem(atPath: myDocumentPath)
        } catch let error { print(error) }
    }

    // File to composit
    let asset = AVURLAsset(url: videoURL as URL)
    let composition = AVMutableComposition.init()
    composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)

    let clipVideoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]


    // Rotate to potrait
   let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)


    let videoTransform:CGAffineTransform = clipVideoTrack.preferredTransform



    //fix orientation
    var videoAssetOrientation_  = UIImage.Orientation.right

    var isVideoAssetPortrait_  = false

    var text = "none"

    if videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0 {
        videoAssetOrientation_ = UIImage.Orientation.right
        isVideoAssetPortrait_ = true
        text = "right"
    }
    if videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == 1.0 && videoTransform.d == 0 {
        videoAssetOrientation_ = UIImage.Orientation.right
        isVideoAssetPortrait_ = true
        text = "special"
        print("this bitch is special :)")
    }
    if videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0 {
        videoAssetOrientation_ =  UIImage.Orientation.left
        isVideoAssetPortrait_ = true
        text = "left"
    }
    if videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0 {
        videoAssetOrientation_ =  UIImage.Orientation.up
        text = "up)"
    }
    if videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0 {
        videoAssetOrientation_ = UIImage.Orientation.down;
        text = "down"
    }

    print("width: \(clipVideoTrack.naturalSize.width),height:\(clipVideoTrack.naturalSize.height)")
    if text == "special"{
        print(clipVideoTrack.preferredTransform)
        let transform = CGAffineTransform(a: 0, b: 1, c: 1, d: 0, tx: 00, ty: 0)
        transformer.setTransform(transform.translatedBy(x: 0, y: 0), at: CMTime.zero)

    }else{
        print(clipVideoTrack.preferredTransform)
        transformer.setTransform(clipVideoTrack.preferredTransform, at: CMTime.zero)
    }
    print("width: \(clipVideoTrack.naturalSize.width),height:\(clipVideoTrack.naturalSize.height)")
    print("SIZES: \(videoTransform.a),\(videoTransform.b),\(videoTransform.c),\(videoTransform.tx),\(videoTransform.d),\(videoTransform.ty),")
    print("VIdeo Asset Oreintation: \(text)")
   transformer.setOpacity(0.0, at: asset.duration)




    //adjust the render size if neccessary
   var naturalSize: CGSize
    if(isVideoAssetPortrait_){
        naturalSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.width)
    } else {
        naturalSize = clipVideoTrack.naturalSize;
    }

    var renderWidth: CGFloat!
    var renderHeight: CGFloat!

    renderWidth = naturalSize.width
    renderHeight = naturalSize.height


    let parentlayer = CALayer()
    let videoLayer = CALayer()
    let watermarkLayer = CALayer()


    let videoComposition = AVMutableVideoComposition()
    videoComposition.renderSize = CGSize(width: renderWidth, height: renderHeight)
    videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
    videoComposition.renderScale = 1.0



    watermarkLayer.contents = tempImageView.asImage().cgImage



    parentlayer.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: naturalSize)
    videoLayer.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: naturalSize)
    watermarkLayer.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: naturalSize)




    parentlayer.addSublayer(videoLayer)
    parentlayer.addSublayer(watermarkLayer)

    // Add watermark to video
    videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayers: [videoLayer], in: parentlayer)

    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: CMTimeMakeWithSeconds(60, preferredTimescale: 30))


    instruction.layerInstructions = [transformer]
    videoComposition.instructions = [instruction]

    let exporter = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetHighestQuality)
    exporter?.outputFileType = AVFileType.mov
    exporter?.outputURL = filePath
    exporter?.videoComposition = videoComposition

    exporter!.exportAsynchronously(completionHandler: {() -> Void in
        if exporter?.status == .completed {
            let outputURL: URL? = exporter?.outputURL
            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputURL!)
            }) { saved, error in
                if saved {
                    ProgressHUD.showSuccess("Video Saved")
                    let fetchOptions = PHFetchOptions()
                    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
                    let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions).lastObject
                    PHImageManager().requestAVAsset(forVideo: fetchResult!, options: nil, resultHandler: { (avurlAsset, audioMix, dict) in
                        let newObj = avurlAsset as! AVURLAsset
                        print(newObj.url)
                        DispatchQueue.main.async(execute: {
                            print(newObj.url.absoluteString)
                        })
                    })
                    print (fetchResult!)
                }
            }
        }
    })


}

在此先感谢您的帮助,如果您有任何疑问或疑问,请告诉我。

0 个答案:

没有答案