IOS Video Compression Swift iOS 8 corrupt video file

前端 未结 4 1382
轻奢々
轻奢々 2020-11-30 20:49

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

4条回答
  •  盖世英雄少女心
    2020-11-30 21:19

    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()
    
                        })
                    }
                 })
    

提交回复
热议问题