I am trying to compress video taken with the users camera from UIImagePickerController (Not an existing video but one on the fly) to upload to my server and take a small amo
Figured it out! Ok so there were 2 problems: 1 problem was with the videoWriter.finishWritingWithCompletionHandler function call. when this completion block gets executed it DOES NOT MEAN that the video writer has finished writing to the output url. So i had to check if the status was completed before i uploaded the actual video file. It's kind of a hack but this is what i did
videoWriter.finishWritingWithCompletionHandler({() -> Void in
while true
{
if videoWriter.status == .Completed
{
var data = NSData(contentsOfURL: outputURL)!
println("Finished: Byte Size After Compression: \(data.length / 1048576) mb")
Networking().uploadVideo(data, fileName: "Video")
self.dismissViewControllerAnimated(true, completion: nil)
break
}
}
})
The second problem I was having was a Failed status and that was because i kept writing to the same temp directory as shown in the code for the UIImagePickerController didFinishSelectingMediaWithInfo method in my question. So i just used the current date as a directory name so it would be unique.
var uploadUrl = NSURL.fileURLWithPath(NSTemporaryDirectory().stringByAppendingPathComponent("\(NSDate())").stringByAppendingString(".mov"))
[EDIT]: BETTER SOLUTION
Ok so after a lot of experimenting and months later I've found a damn good and much simpler solution for getting a video down from 45 mb down to 1.42 mb with pretty good quality.
Below is the function to call instead of the original convertVideo function. note that i had to write my own completion handler paramater which is called after the asynchronous export has finished. i just called it handler.
func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void)
{
var urlAsset = AVURLAsset(URL: inputURL, options: nil)
var exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality)
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession.shouldOptimizeForNetworkUse = true
exportSession.exportAsynchronouslyWithCompletionHandler { () -> Void in
handler(session: exportSession)
}
}
And here is the code in the uiimagepickercontrollerDidFinisPickingMediaWithInfo function.
self.compressVideo(inputURL!, outputURL: uploadUrl!, handler: { (handler) -> Void in
if handler.status == AVAssetExportSessionStatus.Completed
{
var data = NSData(contentsOfURL: uploadUrl!)
println("File size after compression: \(Double(data!.length / 1048576)) mb")
self.picker.dismissViewControllerAnimated(true, completion: nil)
}
else if handler.status == AVAssetExportSessionStatus.Failed
{
let alert = UIAlertView(title: "Uh oh", message: " There was a problem compressing the video maybe you can try again later. Error: \(handler.error.localizedDescription)", delegate: nil, cancelButtonTitle: "Okay")
alert.show()
})
}
})