在我的应用程序中,用户可以记录多个纵向视频,这些视频存储在AVAsset数组中,然后在下面附加的功能中合并到一个视频文件中。在合并过程中,视频已旋转为横向,通过变换动作,我已经能够将其旋转为纵向。 导出的视频是水平翻转的-如何在不水平翻转的情况下将视频旋转为纵向?
func mergeVideoArray(){
//This merges all video files of the array that we just recorded.
var arrayVideos = self.videoArray //Videos Array
var atTimeM: CMTime = CMTimeMake(0, 0)
var lastAsset: AVAsset!
var layerInstructionsArray = [AVVideoCompositionLayerInstruction]()
var completeTrackDuration: CMTime = CMTimeMake(0, 1)
var videoSize: CGSize = CGSize(width: 0.0, height: 0.0)
var totalTime : CMTime = CMTimeMake(0, 0)
let mixComposition = AVMutableComposition()
let videoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let soundTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
for videoAsset in arrayVideos {
do {
try videoTrack!.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaType.video)[0], at: totalTime)
try soundTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaType.audio)[0], at: totalTime)
videoSize = (videoTrack?.naturalSize)!
}
catch let error as NSError { print("error: \(error.localizedDescription)") }
totalTime = CMTimeAdd(atTimeM, videoAsset.duration) // <-- Update the total time for all videos.
completeTrackDuration = CMTimeAdd(completeTrackDuration, videoAsset.duration)
//Rotates the video to portrait
let videoInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack!)
var transform:CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0)
transform = transform.translatedBy(x: -((videoTrack?.naturalSize.width)!), y: 0.0)
transform = transform.rotated(by: CGFloat(Double.pi/2))
transform = transform.translatedBy(x: 0.0, y: -((videoTrack?.naturalSize.width)!))
videoInstruction.setTransform(transform, at: kCMTimeZero)
if videoAsset != videoArray.last{
videoInstruction.setOpacity(0.0, at: completeTrackDuration)
}
layerInstructionsArray.append(videoInstruction)
lastAsset = videoAsset
}
let mainInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, completeTrackDuration)
mainInstruction.layerInstructions = layerInstructionsArray
let mainComposition = AVMutableVideoComposition()
mainComposition.instructions = [mainInstruction]
mainComposition.frameDuration = CMTimeMake(1, 30)
mainComposition.renderSize = CGSize(width: videoSize.height, height: videoSize.width)
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = dateFormatter.string(from: NSDate() as Date)
let savePath = (documentDirectory as NSString).appendingPathComponent("mergeVideo-\(date).mov")
let url = NSURL(fileURLWithPath: savePath)
let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
exporter!.outputURL = url as URL
exporter!.outputFileType = AVFileType.mp4
exporter!.shouldOptimizeForNetworkUse = true
exporter!.videoComposition = mainComposition
exporter!.exportAsynchronously {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: exporter!.outputURL!)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else{
print("video erro: \(error?.localizedDescription)")
}
}
}
}