Search code examples
iosswiftxcodevideoavassetexportsession

Swift - Compressing video files


So, at the moment I am using this to compress video:

func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void)
    {
        let urlAsset = AVURLAsset(URL: inputURL, options: nil)

        let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality)

        exportSession!.outputURL = outputURL

        exportSession!.outputFileType = AVFileTypeQuickTimeMovie

        exportSession!.shouldOptimizeForNetworkUse = true

        exportSession!.exportAsynchronouslyWithCompletionHandler { () -> Void in

            handler(session: exportSession!)
        }

    }

When I recorded a video in 2 seconds, the size was 4,3 MB and when I recorded a video in 6 seconds the file size was 9,3 MB.

Any tips to reduce the size?


Solution

  • This extension focuses on exporting it to a lower quality setting (in this case Medium) and uses an mp4 container, over the mov container favored by iOS. This can result in a loss of quality, but you can experiment with higher output settings and different formats as you work to fine tune your output.

    extension PreviewVideoViewController: AVCaptureFileOutputRecordingDelegate {
        func fileOutput(_ output: AVCaptureFileOutput,
                        didFinishRecordingTo outputFileURL: URL,
                        from connections: [AVCaptureConnection],
                        error: Error?) {
            guard let data = try? Data(contentsOf: outputFileURL) else {
                return
            }
    
            print("File size before compression: \(Double(data.count / 1048576)) mb")
    
            let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + UUID().uuidString + ".mp4")
            compressVideo(inputURL: outputFileURL as URL,
                          outputURL: compressedURL) { exportSession in
                guard let session = exportSession else {
                    return
                }
    
                switch session.status {
                case .unknown:
                    break
                case .waiting:
                    break
                case .exporting:
                    break
                case .completed:
                    guard let compressedData = try? Data(contentsOf: compressedURL) else {
                        return
                    }
    
                    print("File size after compression: \(Double(compressedData.count / 1048576)) mb")
                case .failed:
                    break
                case .cancelled:
                    break
                }
            }
        }
    
    
        func compressVideo(inputURL: URL,
                           outputURL: URL,
                           handler:@escaping (_ exportSession: AVAssetExportSession?) -> Void) {
            let urlAsset = AVURLAsset(url: inputURL, options: nil)
            guard let exportSession = AVAssetExportSession(asset: urlAsset,
                                                           presetName: AVAssetExportPresetMediumQuality) else {
                handler(nil)
    
                return
            }
    
            exportSession.outputURL = outputURL
            exportSession.outputFileType = .mp4
            exportSession.exportAsynchronously {
                handler(exportSession)
            }
        }
    }