5

I am merging multiply videos (implantation of pause button) and everything working fine except when merging video from the back camera with video from front camera then one of the videos comes turned upside down in the new video(merged video). My code:

let mixComposition = AVMutableComposition() 

let videoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
let trackAudio = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

var insertTime = kCMTimeZero
for var i = 0; i < currentAssets.count; i++ {
    let tracks = currentAssets[i].tracksWithMediaType(AVMediaTypeVideo)
    let audios = currentAssets[i].tracksWithMediaType(AVMediaTypeAudio)
                    
    let assetTrack:AVAssetTrack = tracks[0] as AVAssetTrack
    try videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, currentAssets[i].duration), ofTrack: assetTrack, atTime: insertTime)
    let assetTrackAudio:AVAssetTrack = audios[0] as AVAssetTrack
    try trackAudio.insertTimeRange(CMTimeRangeMake(kCMTimeZero, currentAssets[i].duration), ofTrack: assetTrackAudio, atTime: insertTime)
    insertTime = CMTimeAdd(insertTime, currentAssets[i].duration)
}
videoTrack.preferredTransform = assetTrack.preferredTransform

let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,inDomains: .UserDomainMask).last!
let mediaURL = documentsURL.URLByAppendingPathComponent(AppMediaFolder)
let savePath = mediaURL.URLByAppendingPathComponent("\(NSUUID().UUIDString).mp4").path!
        
self.createDirectoryIfExists(mediaURL)
let url = NSURL(fileURLWithPath: savePath)
        
currentAssets.removeAll()
currentAssets.append(AVAsset(URL: url))
        
//Create Exporter
let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
exporter.outputURL = url
exporter.outputFileType = AVFileTypeMPEG4
exporter.shouldOptimizeForNetworkUse = true
                
Vukašin Manojlović
  • 3,717
  • 3
  • 19
  • 31
Ivan Slavov
  • 270
  • 3
  • 12

1 Answers1

5

You need to be careful with the renderSize of your AVMutableVideoComposition and the transform of the AVMutableVideoCompositionLayerInstruction.

To properly align them, you need to both translate and rotate the video with the correct degrees. To flip it upside down you need to rotate it by 180 degrees and translate it to the proper coordinates:

...
videoComposition.renderSize = CGSizeMake(X, Y)
...
let translate = CGAffineTransformMakeTranslation(X, Y);
let rotate = CGAffineTransformRotate(translate, CGFloat(ANGLE_IN_RADIANS))
...    

In my case, the renderSize and the translation are set to 1280 and 720 and the 180 degree rotation is basically M_PI in radians:

let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSizeMake(1280, 720)
videoComposition.frameDuration = CMTimeMake(1, 30)

let videoInstruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(180, 30))

let transformInstruction:AVMutableVideoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)
let translate = CGAffineTransformMakeTranslation(1280, 720);
let rotate = CGAffineTransformRotate(translate, CGFloat(M_PI))

transformInstruction.setTransform(rotate, atTime: kCMTimeZero)
videoInstruction.layerInstructions = [transformInstruction]
videoComposition.instructions = [videoInstruction]

In the end, you will still need to add this videoComposition to your AVAssetExportSession for the transformations to take effect.

gigo
  • 152
  • 7
  • 1
    can you please elaborate your answer?? I am facing the same problem @gigo – pigeon_39 Apr 17 '17 at 07:02
  • 2
    Where you specify timeRange, shouldn't that say "videoInstruction" and not "instruction"? What is "clipVideoTrack"? – Chewie The Chorkie Apr 12 '18 at 19:45
  • I needed 720x1280 and these lines are what fixed the rotation issue for me: `let translate = CGAffineTransformMakeTranslation(720, 1280); let rotate = CGAffineTransformRotate(translate, CGFloat(M_PI)` but in **Swift**: `let translate = CGAffineTransform(translationX: 720, y: 1280); let rotate = translate.rotated(by: CGFloat(Double.pi))` – Lance Samaria May 01 '22 at 03:26