Swift - How to record video in MP4 format with UIImagePickerController?

Kautham Krishna picture Kautham Krishna · Nov 1, 2016 · Viewed 17.9k times · Source

I am creating a app in which i need to record videos and upload it to a server. Now my project has a android version too. To support android version i have to record the videos in mp4 format. I followed this tutorial to set the UIImagePicker media type to movie format imagePicker.mediaTypes = [kUTTypeMovie as String]

The UIImagePickerController is perfect for my requirement and the only thing that i need to change is its saving format to mp4. I tried kUTTypeMPEG4 in mediaTypes but it throws error at the run time with no error description.

This is my video Capture function

func startCameraFromViewController() {

        if UIImagePickerController.isSourceTypeAvailable(.Camera) == false {
            return
        }
        viewBlack.hidden = false
        presentViewController(cameraController, animated: false, completion: nil)

        cameraController.sourceType = .Camera

        cameraController.mediaTypes = [kUTTypeMovie as String]
        //cameraController.mediaTypes = [kUTTypeMPEG4 as String]
        cameraController.cameraCaptureMode = .Video
        cameraController.videoQuality = .TypeMedium
        if(getPurchaseId() as! Int == 0)
        {
            if(txtBenchMark.text?.isEmpty == false)
            {
                cameraController.videoMaximumDuration = NSTimeInterval(300.0)
            }else{
                cameraController.videoMaximumDuration = NSTimeInterval(60.0)
            }
        }else{
            cameraController.videoMaximumDuration = NSTimeInterval(600.0)
        }
        cameraController.allowsEditing = false
    }

I am using Swift 2.2 and Xcode 8 with Use Legacy swift Language version = Yes

Any Alternative Solutions are also appreciated. Thanks in advance.

EDIT: I found out that there is no method to directly record videos in mp4 format in swift. only can be converted to required format from apple's quicktime mov format.

Answer

William Taylor picture William Taylor · Nov 1, 2016

Here is some code that you can use to convert the recorded video into MP4:

func encodeVideo(videoURL: NSURL)  {
let avAsset = AVURLAsset(URL: videoURL, options: nil)

var startDate = NSDate()

//Create Export session
exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)

// exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
//Creating temp path to save the converted video


let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let myDocumentPath = NSURL(fileURLWithPath: documentsDirectory).URLByAppendingPathComponent("temp.mp4").absoluteString
let url = NSURL(fileURLWithPath: myDocumentPath)

let documentsDirectory2 = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL

let filePath = documentsDirectory2.URLByAppendingPathComponent("rendered-Video.mp4")
deleteFile(filePath)

//Check if the file already exists then remove the previous file
if NSFileManager.defaultManager().fileExistsAtPath(myDocumentPath) {
    do {
        try NSFileManager.defaultManager().removeItemAtPath(myDocumentPath)
    }
    catch let error {
        print(error)
    }
}

 url

exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileTypeMPEG4
exportSession!.shouldOptimizeForNetworkUse = true
var start = CMTimeMakeWithSeconds(0.0, 0)
var range = CMTimeRangeMake(start, avAsset.duration)
exportSession.timeRange = range

exportSession!.exportAsynchronouslyWithCompletionHandler({() -> Void in
    switch self.exportSession!.status {
    case .Failed:
        print("%@",self.exportSession?.error)
    case .Cancelled:
        print("Export canceled")
    case .Completed:
        //Video conversion finished
        var endDate = NSDate()

        var time = endDate.timeIntervalSinceDate(startDate)
        print(time)
        print("Successful!")
        print(self.exportSession.outputURL)

    default:
        break
    }

})


}

func deleteFile(filePath:NSURL) {
guard NSFileManager.defaultManager().fileExistsAtPath(filePath.path!) else {
    return
}

do {
    try NSFileManager.defaultManager().removeItemAtPath(filePath.path!)
}catch{
    fatalError("Unable to delete file: \(error) : \(__FUNCTION__).")
}
}

Source: https://stackoverflow.com/a/39329155/4786204