title: IOS Video Compression Swift iOS 8 corrupt video file
body: <p>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 amount of time to do so, so a smaller size is ideal instead of 30-45 mb on newer quality cameras.</p>
  
  <p>Here is the code to do a compression in swift for iOS 8 and it compresses wonderfully, i go from 35 mb down to 2.1 mb easily. </p>
  
  <pre><code>   func convertVideo(inputUrl: NSURL, outputURL: NSURL) 
     {
      //setup video writer
      var videoAsset = AVURLAsset(URL: inputUrl, options: nil) as AVAsset
  
      var videoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack
  
      var videoSize = videoTrack.naturalSize
  
      var videoWriterCompressionSettings = Dictionary(dictionaryLiteral:(AVVideoAverageBitRateKey,NSNumber(integer:960000)))
  
      var videoWriterSettings = Dictionary(dictionaryLiteral:(AVVideoCodecKey,AVVideoCodecH264),
          (AVVideoCompressionPropertiesKey,videoWriterCompressionSettings),
          (AVVideoWidthKey,videoSize.width),
          (AVVideoHeightKey,videoSize.height))
  
      var videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoWriterSettings)
  
      videoWriterInput.expectsMediaDataInRealTime = true
  
      videoWriterInput.transform = videoTrack.preferredTransform
  
  
      var videoWriter = AVAssetWriter(URL: outputURL, fileType: AVFileTypeQuickTimeMovie, error: nil)
  
      videoWriter.addInput(videoWriterInput)
  
      var videoReaderSettings: [String:AnyObject] = [kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]
  
      var videoReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoReaderSettings)
  
      var videoReader = AVAssetReader(asset: videoAsset, error: nil)
  
      videoReader.addOutput(videoReaderOutput)
  
  
  
      //setup audio writer
      var audioWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: nil)
  
      audioWriterInput.expectsMediaDataInRealTime = false
  
      videoWriter.addInput(audioWriterInput)
  
  
      //setup audio reader
  
      var audioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as AVAssetTrack
  
      var audioReaderOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: nil) as AVAssetReaderOutput
  
      var audioReader = AVAssetReader(asset: videoAsset, error: nil)
  
  
      audioReader.addOutput(audioReaderOutput)
  
      videoWriter.startWriting()
  
  
      //start writing from video reader
      videoReader.startReading()
  
      videoWriter.startSessionAtSourceTime(kCMTimeZero)
  
      //dispatch_queue_t processingQueue = dispatch_queue_create("processingQueue", nil)
  
      var queue = dispatch_queue_create("processingQueue", nil)
  
      videoWriterInput.requestMediaDataWhenReadyOnQueue(queue, usingBlock: { () -&gt; Void in
          println("Export starting")
  
          while videoWriterInput.readyForMoreMediaData
          {
              var sampleBuffer:CMSampleBufferRef!
  
              sampleBuffer = videoReaderOutput.copyNextSampleBuffer()
  
              if (videoReader.status == AVAssetReaderStatus.Reading &amp;&amp; sampleBuffer != nil)
              {
                  videoWriterInput.appendSampleBuffer(sampleBuffer)
  
              }
  
              else
              {
                  videoWriterInput.markAsFinished()
  
                  if videoReader.status == AVAssetReaderStatus.Completed
                  {
                      if audioReader.status == AVAssetReaderStatus.Reading || audioReader.status == AVAssetReaderStatus.Completed
                      {
  
                      }
                      else {
  
  
                          audioReader.startReading()
  
                          videoWriter.startSessionAtSourceTime(kCMTimeZero)
  
                          var queue2 = dispatch_queue_create("processingQueue2", nil)
  
  
                          audioWriterInput.requestMediaDataWhenReadyOnQueue(queue2, usingBlock: { () -&gt; Void in
  
                              while audioWriterInput.readyForMoreMediaData
                              {
                                  var sampleBuffer:CMSampleBufferRef!
  
                                  sampleBuffer = audioReaderOutput.copyNextSampleBuffer()
  
                                  println(sampleBuffer == nil)
  
                                  if (audioReader.status == AVAssetReaderStatus.Reading &amp;&amp; sampleBuffer != nil)
                                  {
                                      audioWriterInput.appendSampleBuffer(sampleBuffer)
  
                                  }
  
                                  else
                                  {
                                      audioWriterInput.markAsFinished()
  
                                      if (audioReader.status == AVAssetReaderStatus.Completed)
                                      {
  
                                          videoWriter.finishWritingWithCompletionHandler({ () -&gt; Void in
  
                                              println("Finished writing video asset.")
  
                                              self.videoUrl = outputURL
  
                                                  var data = NSData(contentsOfURL: outputURL)!
  
                                                   println("Byte Size After Compression: \(data.length / 1048576) mb")
  
                                                  println(videoAsset.playable)
  
                                                  //Networking().uploadVideo(data, fileName: "Test2")
  
                                              self.dismissViewControllerAnimated(true, completion: nil)
  
                                          })
                                          break
                                      }
                                  }
                              }
                          })
                          break
                      }
                  }
              }// Second if
  
          }//first while
  
      })// first block
     // return
  }
  </code></pre>
  
  <p>Here is the code for my UIImagePickerController that calls the compress method</p>
  
  <pre><code>func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
  {
      // Extract the media type from selection
  
      let type = info[UIImagePickerControllerMediaType] as String
  
      if (type == kUTTypeMovie)
      {
  
          self.videoUrl = info[UIImagePickerControllerMediaURL] as? NSURL
  
          var uploadUrl = NSURL.fileURLWithPath(NSTemporaryDirectory().stringByAppendingPathComponent("captured").stringByAppendingString(".mov"))
  
          var data = NSData(contentsOfURL: self.videoUrl!)!
  
          println("Size Before Compression: \(data.length / 1048576) mb")
  
  
          self.convertVideo(self.videoUrl!, outputURL: uploadUrl!)
  
          // Get the video from the info and set it appropriately.
  
          /*self.dismissViewControllerAnimated(true, completion: { () -&gt; Void in
  
  
          //self.next.enabled = true
  
          })*/
      }
  }
  </code></pre>
  
  <p>As i mentioned above this works as far as file size reduction, but when i get the file back (it is still of type .mov) quicktime cannot play it. Quicktime does try to convert it initially but fails halfway through (1-2 seconds after opening the file.) I've even tested the video file in AVPlayerController but it doesn't give any info about the movie, its just a play button without ant loading and without any length just "--" where the time is usually in the player. IE a corrupt file that won't play.</p>
  
  <p>Im sure it has something to do with the settings for writing the asset out wether it is the video writing or the audio writing I'm not sure at all. It could even be the reading of the asset that is causing it to be corrupt. I've tried changing the variables around and setting different keys for reading and writing but i haven't found the right combination and this sucks that i can compress but get a corrupt file out of it. I'm not sure at all and any help would be appreciated. Pleeeeeeeeease.</p>