Roduck Nickes Roduck Nickes - 25 days ago 35
iOS Question

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?

Answer

While these extensions both use the medium setting for compression, you can change it to low or high if you want to focus on quality or size.

I use these extensions based on Swift version:

For OP (Swift 2.2):

extension PreviewVideoViewController: AVCaptureFileOutputRecordingDelegate {
    func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
        let data = NSData(contentsOfURL: outputFileURL)
        print("File size before compression: \(Double(data!.length / 1048576)) mb")
        let compressedURL = NSURL.fileURLWithPath(NSTemporaryDirectory() + NSUUID().UUIDString + ".m4v")
        compressVideo(outputFileURL, outputURL: compressedURL) { (session) in
            switch session.status {
            case .Unknown:
                break
            case .Waiting:
                break
            case .Exporting:
                break
            case .Completed:
                let data = NSData(contentsOfURL: compressedURL)
                print("File size after compression: \(Double(data!.length / 1048576)) mb")
            case .Failed:
                break
            case .Cancelled:
                break
            }
        }
    }

    private func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void) {
        let urlAsset = AVURLAsset(URL: inputURL, options: nil)
        if let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality) {
            exportSession.outputURL = outputURL
            exportSession.outputFileType = AVFileTypeQuickTimeMovie
            exportSession.shouldOptimizeForNetworkUse = true
            exportSession.exportAsynchronouslyWithCompletionHandler { () -> Void in
                handler(session: exportSession)
            }
        }
    }
}

For someone who needs it in Swift 3.0:

extension PreviewVideoViewController: AVCaptureFileOutputRecordingDelegate {
    func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
        guard let data = NSData(contentsOf: outputFileURL as URL) else {
            return
        }

        print("File size before compression: \(Double(data.length / 1048576)) mb")
        let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".m4v")
        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 = NSData(contentsOf: compressedURL) else {
                    return
                }

                print("File size after compression: \(Double(compressedData.length / 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 = AVFileTypeQuickTimeMovie
        exportSession.shouldOptimizeForNetworkUse = true
        exportSession.exportAsynchronously { () -> Void in
            handler(exportSession)
        }
    }
}
Comments