URL+Extension.swift 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import Foundation
  2. import AVKit
  3. extension URL {
  4. enum ConversionError: Error {
  5. case runtimeError(String)
  6. }
  7. public var queryParameters: [String: String]? {
  8. guard
  9. let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
  10. let queryItems = components.queryItems else { return nil }
  11. return queryItems.reduce(into: [String: String]()) { result, item in
  12. result[item.name] = item.value
  13. }
  14. }
  15. public func convertToMp4(completionHandler: ((URL?, Error?) -> Void)?) {
  16. let avAsset = AVURLAsset(url: self, options: nil)
  17. AVAssetExportSession.determineCompatibility(ofExportPreset: AVAssetExportPresetPassthrough,
  18. with: avAsset,
  19. outputFileType: .mp4,
  20. completionHandler: { (isCompatible) in
  21. if !isCompatible {
  22. completionHandler?(nil, ConversionError.runtimeError("File has incompatible file format for mp4 conversion"))
  23. return
  24. }
  25. guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) else {
  26. completionHandler?(nil, ConversionError.runtimeError("Could not initiate AVAssertExportSession"))
  27. return
  28. }
  29. let filename = self.deletingPathExtension().lastPathComponent.replacingOccurrences(of: ".", with: "-").appending(".mp4")
  30. let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)
  31. if FileManager.default.fileExists(atPath: outputURL.path) {
  32. do {
  33. try FileManager.default.removeItem(at: outputURL)
  34. } catch {
  35. completionHandler?(nil, error)
  36. }
  37. }
  38. exportSession.outputURL = outputURL
  39. exportSession.outputFileType = AVFileType.mp4
  40. exportSession.shouldOptimizeForNetworkUse = true
  41. let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
  42. let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
  43. exportSession.timeRange = range
  44. exportSession.exportAsynchronously(completionHandler: {() -> Void in
  45. switch exportSession.status {
  46. case .failed:
  47. completionHandler?(nil, exportSession.error)
  48. case .cancelled:
  49. completionHandler?(nil, nil)
  50. case .completed:
  51. completionHandler?(exportSession.outputURL, nil)
  52. default: break
  53. }
  54. })
  55. })
  56. }
  57. }