0

I use the well known PBJVision to record videos which then must be combined together. I use AVMutableComposition to combine videos using insertTimeRange(_:ofAsset:atTime:error:). It works well if the videos have been taken with the same camera. But for example if one is taken with back camera then take another using the front camera the latter video's video is missing. Looks like only the audio is added. Here is my code:

var error: NSError? = nil

    let composition = AVMutableComposition()

    var currentTime = kCMTimeZero

    for (index, videoURL) in enumerate(videoURLS) {
        let asset = AVURLAsset.assetWithURL(videoURL) as! AVAsset

        let success = composition.insertTimeRange(CMTimeRange(start: kCMTimeZero, duration: asset.duration),
            ofAsset: asset,
            atTime: currentTime,
            error: &error)
        if !success {
            if error != nil {
                println("timerange isnert error - \(error?.localizedDescription)")
            }
        }

        // add time till we get to the last video
        if index < videoURLS.count - 1 {
            currentTime = CMTimeAdd(currentTime, asset.duration)
        }
    }

    let outputURL = fileSystemHelper.temporaryStorageURLForExportSession()
    let fileManager = NSFileManager.defaultManager()
    fileManager.removeItemAtURL(outputURL, error: &error)
    if error != nil {
        println("export session file removal error - \(error?.localizedDescription)")
    }

    let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)
    exportSession.outputFileType = AVFileTypeMPEG4
    exportSession.outputURL = outputURL

    let start = CMTimeMake(0, 1)
    let range = CMTimeRangeMake(start, composition.duration)
    //exportSession.timeRange = range

    exportSession.exportAsynchronouslyWithCompletionHandler { () -> Void in
        switch exportSession.status {
        case .Completed:
            self.fileSystemHelper.copyFileAtURL(outputURL, toURL: finalURL)

            self.appendURL = nil
            //  self.isRecording = false

            completion()
        case .Failed:
            println("fail error - \(exportSession.error.localizedDescription)")

            self.fileSystemHelper.removeFileAtURL(outputURL)
            self.appendURL = nil
            //self.isRecording = false

            println("failed to mix")
            //  delegate?.videoCaptureDidFinishRecordingVideoAtURL(URL, appended: appendURL == nil)

        default:
            println("something else happened, check code")
        }
    }
i-konov
  • 842
  • 1
  • 7
  • 19

1 Answers1

0

I found the answer myself over a night walk around the neighborhood just after I asked this question :) So the different cameras have different Maximum Possible Resolutions thus producing frames with different sizes that confuses the composition object. It uses the size of the first video and ignores frames of a video with a different size. So test and see what is the best possible resolution AVCaptureSessionPreset supported by both cameras on particular a device. Then use that preset in your video capture code and do not jump directly to using AVCaptureSessionPresetHigh.

I hope this helps to other people too :)

i-konov
  • 842
  • 1
  • 7
  • 19
  • Could you elaborate a bit more on _"So test and see what is the best possible resolution both cameras have on a device and set the preset to it not directly to AVCaptureSessionPresetHigh."_? Thanks in advance. – Unheilig May 28 '15 at 11:34
  • This means that you will check which is the highest AVCaptureSessionPreset constant that includes specific resolution is supported by both AVCaptureDevice objects representing the front and rear camera of the device. And set this to be the preset you will use to capture video thus ensuring frames taken by any device are in the same size. – i-konov May 28 '15 at 11:37
  • Other words - use the one that is highest from one of the two devices? What is unclear to me is this - _"set the preset to it not directly to AVCaptureSessionPresetHigh."_. Thanks again. – Unheilig May 28 '15 at 11:40