AVMutableComposition()视频以横向导出(从纵向旋转)

时间:2018-12-17 03:36:20

标签: swift avfoundation cgaffinetransform avmutablecomposition avkit

我有一个视频,我要在上面添加图像叠加层。视频是纵向的,但是当我导出视频时,它是旋转的(但是我叠加的图像却没有旋转)。导出的视频也进行了超级放大,但是我认为这是因为我的resizeAspectFill以及它以横向导出的事实。

我尝试过旋转videoLayerInstruction,但无法使其工作

    let overlayImage = mediaView.asImage()

    // Create main composition & its tracks
    let mainComposition = AVMutableComposition()
    let compositionVideoTrack = mainComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
    let compositionAudioTrack = mainComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))

    // Get source video & audio tracks
    let videoAsset = AVURLAsset(url: videoURL, options: nil)
    let sourceVideoTrack = videoAsset.tracks(withMediaType: AVMediaType.video)[0]
    let sourceAudioTrack = videoAsset.tracks(withMediaType: AVMediaType.audio)[0]

    // Add source tracks to composition
    do {
        try compositionVideoTrack?.insertTimeRange(CMTimeRange(start: CMTime.zero, duration: videoAsset.duration), of: sourceVideoTrack, at: CMTime.zero)
        compositionVideoTrack?.preferredTransform = sourceVideoTrack.preferredTransform
        try compositionAudioTrack?.insertTimeRange(CMTimeRange(start: CMTime.zero, duration: videoAsset.duration), of: sourceAudioTrack, at: CMTime.zero)
    } catch {
        print("Error with insertTimeRange while exporting video: \(error)")
    }

    // Create video composition
    let videoComposition = AVMutableVideoComposition()

    // -- Set parent layer & set size equal to device bounds
    let parentLayer = CALayer()
    parentLayer.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
    parentLayer.backgroundColor = UIColor.red.cgColor
    parentLayer.contentsGravity = CALayerContentsGravity.resizeAspectFill

    // -- Set composition equal to capture settings
    videoComposition.renderSize = CGSize(width: view.frame.width, height: view.frame.width)
    videoComposition.frameDuration = CMTime(value: 1, timescale: Int32(sourceVideoTrack.nominalFrameRate))

    // -- Add instruction to  video composition object
    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRange(start: CMTime.zero, duration: (compositionVideoTrack?.asset!.duration)!)
    let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack!)

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

    // -- Create video layer
    let videoLayer = CALayer()
    videoLayer.frame = parentLayer.frame
    videoLayer.contentsGravity = CALayerContentsGravity.resizeAspectFill

    // -- Create overlay layer
    let overlayLayer = CALayer()
    overlayLayer.frame = parentLayer.frame
    overlayLayer.contentsGravity = CALayerContentsGravity.resizeAspectFill
    overlayLayer.contents = overlayImage.cgImage
    overlayLayer.contentsScale = overlayImage.scale
    overlayLayer.rasterizationScale = 2.0

    // -- Add sublayers to parent layer
    parentLayer.addSublayer(videoLayer)
    parentLayer.addSublayer(overlayLayer)
    overlayLayer.shouldRasterize = true

    // -- Set animation tool
    videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)

    // Create output file
    // Get Path
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
    let outputPath = documentsURL?.appendingPathComponent("newVideoWithLabel.mp4")
    if FileManager.default.fileExists(atPath: (outputPath?.path)!) {
        do {
            try FileManager.default.removeItem(atPath: (outputPath?.path)!)
        }
        catch {
            print ("Error deleting file")
        }
    }

    // Create exporter
    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)!
    exporter.outputURL = outputPath//URL(string: "test111")//videoURL
    exporter.outputFileType = AVFileType.mp4
    exporter.videoComposition = videoComposition
    exporter.shouldOptimizeForNetworkUse = true
    exporter.exportAsynchronously(completionHandler: {
        switch exporter.status{
        case AVAssetExportSession.Status.failed:
            print("failed \(exporter.error)")
        case AVAssetExportSession.Status.cancelled:
            print("cancelled \(exporter.error)")
        default:
            print("Movie complete")

            // play video
            OperationQueue.main.addOperation({ () -> Void in
                self.present(VideoTestVC(videoURL: exporter.outputURL!), animated: true, completion: nil)
            })
        }
    })

0 个答案:

没有答案