【问题标题】:Swift: Square video compositionSwift:方形视频合成
【发布时间】:2017-09-19 08:38:35
【问题描述】:

我正在按照下面的方形视频合成代码

func completeWithVideoAtURL(input: NSURL) {
    let asset = AVAsset(url: input as URL)
    let output = NSURL(fileURLWithPath: NSHomeDirectory() + "/Documents/Video.mp4")

    let session = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality)!
    session.videoComposition = self.squareVideoCompositionForAsset(asset: asset)
    session.outputURL = output as URL
    session.outputFileType = AVFileTypeMPEG4
    session.shouldOptimizeForNetworkUse = true        
    session.exportAsynchronously(completionHandler: { () -> Void in
        DispatchQueue.main.async(execute: { () -> Void in
            // do something with the output
            print("\(output)")
            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: output as URL)
            }) { saved, error in
                if saved {
                    print("saved to gallery")
                }
            }
        })
    })
}

func squareVideoCompositionForAsset(asset: AVAsset) -> AVVideoComposition {
    let track = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
    let length = max(track.naturalSize.width, track.naturalSize.height)

    var transform = track.preferredTransform

    let size = track.naturalSize
    let scale: CGFloat = (transform.a == -1 && transform.b == 0 && transform.c == 0 && transform.d == -1) ? -1 : 1 // check for inversion

    transform = transform.translatedBy(x: scale * -(size.width - length) / 2, y: scale * -(size.height - length) / 2)

    let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
    transformer.setTransform(transform, at: kCMTimeZero)

    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRange(start: kCMTimeZero, duration: kCMTimePositiveInfinity)
    instruction.layerInstructions = [transformer]

    let composition = AVMutableVideoComposition()
    composition.frameDuration = CMTime(value: 1, timescale: 30)
    composition.renderSize = CGSize(width: length, height: length)
    composition.instructions = [instruction]

    return composition
}

squareVideoCompositionForAsset() 函数中,我在 track.naturalSize.width 之间获取 lengthma​​x 值& track.naturalSize.height 因为我不想裁剪视频的任何部分。如果我取最小值,对于纵向视频,它会裁剪视频的上下部分,而对于横向视频,它会裁剪视频的左右部分。

  • 对于横向视频,输出没问题

  • 但是对于纵向视频,输出类似于下图

视频偏左。是否可以将视频居中?任何帮助都会很好,很抱歉长时间的解释。

【问题讨论】:

    标签: ios swift video crop


    【解决方案1】:

    代替这一行

    让缩放:CGFloat = (transform.a == -1 && transform.b == 0 && 变换.c == 0 && 变换.d == -1) ? -1 : 1

    我刚用过这个

        var scale = CGFloat()
        if (transform.a == 0 && transform.b == 1 && transform.c == -1 && transform.d == 0) {
            scale = -1
        }
        else if (transform.a == 0 && transform.b == -1 && transform.c == 1 && transform.d == 0) {
            scale = -1
        }
        else if (transform.a == 1 && transform.b == 0 && transform.c == 0 && transform.d == 1) {
            scale = 1
        }
        else if (transform.a == -1 && transform.b == 0 && transform.c == 0 && transform.d == -1) {
            scale = 1
        }
    

    它就像一个魅力

    【讨论】:

    • 感谢分享!
    【解决方案2】:

    斯威夫特 4.2

    func suqareCropVideo(videoURL: URL, withSide sideLength: CGFloat, completion: @escaping (_ resultURL: URL?, _ error: Error?) -> ()) {
    
        let asset = AVAsset(url: videoURL)
        if let assetVideoTrack = asset.tracks(withMediaType: .video).last {
    
            let originalSize = assetVideoTrack.naturalSize
            var scale: CGFloat
            if originalSize.width < originalSize.height {
                scale = sideLength / originalSize.width
            } else {
                scale = sideLength / originalSize.height
            }
    
            let scaledSize = CGSize(width: originalSize.width * scale, height: originalSize.height * scale)
            let topLeft = CGPoint(x: sideLength * 0.5 - scaledSize.width * 0.5, y: sideLength  * 0.5 - scaledSize.height * 0.5)
    
            let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: assetVideoTrack)
    
            var orientationTransform = assetVideoTrack.preferredTransform
    
            if (orientationTransform.tx == originalSize.width || orientationTransform.tx == originalSize.height) {
                orientationTransform.tx = sideLength
            }
    
            if (orientationTransform.ty == originalSize.width || orientationTransform.ty == originalSize.height) {
                orientationTransform.ty = sideLength
            }
    
            let transform = CGAffineTransform(scaleX: scale, y: scale).concatenating(CGAffineTransform(translationX: topLeft.x, y: topLeft.y)).concatenating(orientationTransform)
    
            layerInstruction.setTransform(transform, at: .zero)
    
    
            let instruction = AVMutableVideoCompositionInstruction()
            instruction.layerInstructions = [layerInstruction]
            instruction.timeRange = assetVideoTrack.timeRange
    
            let videoComposition = AVMutableVideoComposition()
            videoComposition.renderSize = CGSize(width: sideLength, height: sideLength)
            videoComposition.renderScale = 1.0
            videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
            videoComposition.instructions = [instruction]
    
            if let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) {
                export.videoComposition = videoComposition
                export.outputURL = NSURL.fileURL(withPath: "\(NSTemporaryDirectory())\(NSUUID().uuidString).mp4")
                export.outputFileType = AVFileType.mp4
                export.shouldOptimizeForNetworkUse = true
                export.exportAsynchronously {
                    DispatchQueue.main.async {
                        if export.status == .completed {
                            completion(export.outputURL, nil)
                        } else {
                            completion(nil, export.error)
                        }
                    }
                }
            } else {
                completion(nil, nil)
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 2017-08-16
      • 2012-11-16
      • 1970-01-01
      • 1970-01-01
      • 2023-02-15
      相关资源
      最近更新 更多