1

I am trying to compress an AVAsset to lower quality and then export it as an mp4. The input asset could be any type of video that the camera roll allows.

The problem I am running into is that when I try to export an asset to AVAssetExportPresetMediumQuality it fails at the first guard statement when the input is a mp4 file originally. However if I change it to AVAssetExportPresetPassthrough it works but doesn't compress the file. Is there a one way solution to compressing/encoding an asset that could be a .mov or .mp4 originally?

func encodeVideo(asset: AVAsset, completionHandler: @escaping (URL?, String?) -> ())  {
    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else {
        completionHandler(nil, nil)
        return
    }
    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
    let filePath = documentsDirectory.appendingPathComponent("compressed-video.mp4")
    if FileManager.default.fileExists(atPath: filePath.path) {
        do {
            try FileManager.default.removeItem(at: filePath)
        } catch {
            completionHandler(nil, nil)
        }
    }
    exportSession.outputURL = filePath
    exportSession.outputFileType = .mp4
    exportSession.shouldOptimizeForNetworkUse = true
    let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
    let range = CMTimeRangeMake(start: start, duration: asset.duration)
    exportSession.timeRange = range

    exportSession.exportAsynchronously {
        switch exportSession.status {
        case .failed:
            print("Conversion Failed")
            completionHandler(nil, exportSession.error?.localizedDescription)
        case .cancelled:
            print("Conversion Cancelled")
            completionHandler(nil, exportSession.error?.localizedDescription)
        case .completed:
            completionHandler(exportSession.outputURL, nil)
            default: break
        }
    }
}
Nick
  • 247
  • 2
  • 9

2 Answers2

1

Upon some further testing and research this seems to be an issue/possible bug with the simulator (Xcode 11.1 and iPhone 11 Pro simulator, iOS 13.1). Not sure if this extends to other simulators but the above code using AVAssetExportPresetMediumQuality worked on my device testing.

Nick
  • 247
  • 2
  • 9
1

I see you replied to your question saying that the problem is simulator. My advice is to test AVFoundation processes on device. The simulator is not always equipped enough to handle the cases. Also, the problems that may arise on a device, might never show up on the simulator. In any case your code seems valid for conversion to mp4 format. Good luck!