Ios 快速压缩视频文件

Ios 快速压缩视频文件,ios,swift,xcode,video,avassetexportsession,Ios,Swift,Xcode,Video,Avassetexportsession,所以,现在我用这个来压缩视频: func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void) { let urlAsset = AVURLAsset(URL: inputURL, options: nil) let exportSession = AVAssetExportSession(asset: url

所以,现在我用这个来压缩视频:

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!)
        }

    }
当我在2秒内录制视频时,文件大小为4,3 MB,当我在6秒内录制视频时,文件大小为9,3 MB


减少大小的任何提示?

此扩展侧重于将其导出到较低质量的设置(在本例中为中等质量),并使用
mp4
容器,而不是iOS喜欢的
mov
容器。这可能会导致质量下降,但在微调输出时,您可以尝试使用更高的输出设置和不同的格式

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)
        }
    }
}
//使用具有动态比特率的sdavasetexportsession库
func aVodzLatestVideoCompressor(inputURL:URL,aOutputURL:URL,aStartTime:Float,aEndTime:Float){
让sizeVideo:Float=inputURL.verboseFileSizeInMB()
如果sizeVideo<5.0{
DispatchQueue.main.async{
//self.directsendVideowithoutcopressor()
}
返回
}
让startTime=CMTime(秒数:双倍(aStartTime),首选时间刻度:1000)
让endTime=CMTime(秒:双精度(aEndTime),首选时间刻度:1000)
let timeRange=CMTimeRange(开始:开始时间,结束:结束时间)
让anAsset=avurlaste(url:inputURL,选项:nil)
guard let videoTrack=anAsset.tracks(withMediaType:AVMediaType.video)。首先是{return}
变量含水率:浮动=0.0
var duration=anaset.duration
让totalSeconds=Int(CMTimeGetSeconds(持续时间))
打印(“持续时间-\(持续时间)-总秒数-\(总秒数)”)
var比特率=最小值(aQuality,videoTrack.EstimatedDataate)
让landscap=self.isLandScapVideo(afileURL:inputURL)
var originalWidth=videoTrack.naturalSize.width
var originalHeight=videoTrack.naturalSize.height
打印(“原始宽度-\(原始宽度)原始高度-\(原始高度)”)
而(原始宽度>=1920 | |原始高度>=1920){
原始宽度=原始宽度/2
原始高度=原始高度/2
}
var setWidth=Int(原始宽度)
var setlHeight=Int(原始高度)
如果sizeVideo<10.0{
//压缩质量高:
setWidth=Int(原始宽度)
设置高度=整数(原始高度)
水性=浮动(设置宽度*设置高度*20)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则,如果sizeVideo<20.0{
//压缩\质量\介质:
如果总秒数>35{
setWidth=Int(原始宽度/2.7)
设置高度=整数(原始高度/2.7)
}否则,如果总秒数>25{
setWidth=Int(原始宽度/2.3)
设置高度=整数(原始高度/2.3)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则,如果sizeVideo<30.0{
//压缩\质量\介质:
如果总秒数>35{
setWidth=Int(原始宽度/3)
设置高度=整数(原始高度/3)
}否则,如果总秒数>20{
setWidth=Int(原始宽度/2.5)
设置高度=整数(原始高度/2.5)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则{
如果总秒数>35{
setWidth=Int(原始宽度/3.0)
设置高度=整数(原始高度/3.0)
}否则,如果总秒数>25{
setWidth=Int(原始宽度/2.5)
设置高度=整数(原始高度/2.5)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}
印刷品(“水性”)
印刷(浮法(水性))
打印(“比特率”)
打印(浮动(比特率))
let encoder=sdavasetexportsession(资产:anaset)
编码器?.shouldOptimizationForNetworkUse=true
编码器?时间范围=时间范围
编码器?.outputFileType=AVFileType.mp4.rawValue
编码器?.outputURL=AOoutputURL
//960 X 540、1280*720、1920*1080//尺寸缩减参数
编码器?视频设置=[
AVVideoCodeKey:AVVideoCodeType.h264,
AVVideoWidthKey:landscap?NSNumber(值:1280):NSNumber(值:720),
AVVideoHeightKey:landscap?NSNumber(值:720):NSNumber(值:1280),
AVVideoCompressionProperties键:[
AVVideoAverageBitRateKey:NSNumber(值:比特率),
AVVideoProfileLevelKey:AVVideoProfileLevelH264高40
]
]
编码器?音频设置=[
AVFormatIDKey:NSNumber(值:kAudioFormatMPEG4AAC),
AVNumberOfChannelsKey:NSNumber(值:2),
AVSampleRateKey:NSNumber(值:44100),
AVEncoderBitRateKey:NSNumber(值:128000)
]
编码器?.exportAsyn
   func convertVideo(phAsset : PHAsset){

    PHImageManager.default().requestAVAsset(forVideo: phAsset, options: PHVideoRequestOptions(), resultHandler: { (asset, audioMix, info) -> Void in
        if let asset = asset as? AVURLAsset {
            do {
                let videoData = try  Data.init(contentsOf: asset.url)
                print(asset.url)
                self.orginalVideo = asset.url
                print("File size before compression: \(Double(videoData.count / 1048576)) mb")
            let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".MP4")
                print(compressedURL)
                self.compressVideo(inputURL: asset.url , outputURL: compressedURL) { (exportSession) in
                    guard let session = exportSession else {
                        return
                    }
                    switch session.status {
                    case .unknown:
                        print("unknown")
                        break
                    case .waiting:
                        print("waiting")
                        break
                    case .exporting:
                        print("exporting")
                        break
                    case .completed:
                        do {
                        let compressedData = try  Data.init(contentsOf: compressedURL)
                            self.compressVideo = compressedURL
                            print(compressedData)
                             print("File size AFTER compression: \(Double(compressedData.count / 1048576)) mb")
                        }
                        catch{
                           print(error)
                        }


                    case .failed:
                        print("failed")
                        break
                    case .cancelled:
                        print("cancelled")
                        break
                    }
                }
            } catch {
                print(error)
                //return
            }
        }
    })


}

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 = AVFileType.mp4
    exportSession.shouldOptimizeForNetworkUse = true
    exportSession.exportAsynchronously { () -> Void in
        handler(exportSession)
    }
}
//use SDAVAssetExportSession library with dynamic bitrate

func aVodzLatestVideoCompressor(inputURL: URL, aOutputURL: URL, aStartTime:Float, aEndTime:Float)   {
            let sizeVideo:Float = inputURL.verboseFileSizeInMB()
            if  sizeVideo < 5.0 {
                DispatchQueue.main.async {
                   //self.directsendvideowithoutcomressor()
                }
                return
            }
            let startTime = CMTime(seconds: Double(aStartTime), preferredTimescale: 1000)
            let endTime = CMTime(seconds: Double(aEndTime), preferredTimescale: 1000)
            let timeRange = CMTimeRange(start: startTime, end: endTime)
            
            let anAsset = AVURLAsset(url: inputURL, options: nil)
            guard let videoTrack = anAsset.tracks(withMediaType: AVMediaType.video).first else { return }
            var aQuality:Float = 0.0
            var duration = anAsset.duration
            let totalSeconds = Int(CMTimeGetSeconds(duration))
            print("duration -\(duration) - totalSeconds -\(totalSeconds)")
            
            var bitrate = min(aQuality, videoTrack.estimatedDataRate)
            let landscap = self.isLandScapVideo(afileURL: inputURL )
            var originalWidth = videoTrack.naturalSize.width
            var originalHeight  = videoTrack.naturalSize.height
            print("originalWidth -\(originalWidth) originalHeight- \(originalHeight) ")
            while (originalWidth >= 1920 || originalHeight >= 1920) {
                originalWidth = originalWidth / 2
                originalHeight = originalHeight / 2
            }
    
            var setWidth = Int(originalWidth)
            var setlHeight = Int(originalHeight)
            
            if  sizeVideo < 10.0 {
                // COMPRESS_QUALITY_HIGH:
                setWidth = Int(originalWidth)
                setlHeight = Int(originalHeight)
                aQuality = Float(setWidth * setlHeight *  20)
                bitrate = min(aQuality, videoTrack.estimatedDataRate)
            }else if sizeVideo < 20.0 {
                //COMPRESS_QUALITY_MEDIUM:
                if totalSeconds > 35{
                    setWidth = Int(originalWidth /  2.7)
                    setlHeight = Int(originalHeight / 2.7)
                }else if totalSeconds > 25 {
                    setWidth = Int(originalWidth / 2.3)
                    setlHeight = Int(originalHeight / 2.3)
                }else{
                    setWidth = Int(originalWidth / 2.0)
                    setlHeight = Int(originalHeight / 2.0)
                }
                aQuality = Float(setWidth * setlHeight *  10)
                bitrate = min(aQuality, videoTrack.estimatedDataRate)
            }else if sizeVideo < 30.0 {
                //COMPRESS_QUALITY_MEDIUM:
                if totalSeconds > 35{
                    setWidth = Int(originalWidth / 3)
                    setlHeight = Int(originalHeight / 3)
                }else if totalSeconds > 20 {
                    setWidth = Int(originalWidth / 2.5)
                    setlHeight = Int(originalHeight / 2.5)
                }else{
                    setWidth = Int(originalWidth / 2.0)
                    setlHeight = Int(originalHeight / 2.0)
                }
                aQuality = Float(setWidth * setlHeight * 10)
                bitrate = min(aQuality, videoTrack.estimatedDataRate)
            }else{
                if totalSeconds > 35{
                    setWidth = Int(originalWidth / 3.0)
                    setlHeight = Int(originalHeight / 3.0)
                }else if totalSeconds > 25 {
                    setWidth = Int(originalWidth / 2.5)
                    setlHeight = Int(originalHeight / 2.5)
                }else{
                    setWidth = Int(originalWidth / 2.0)
                    setlHeight = Int(originalHeight / 2.0)
                }
                aQuality = Float(setWidth * setlHeight * 10)
                bitrate = min(aQuality, videoTrack.estimatedDataRate)
            }
    
            print("aQuality")
            print(Float(aQuality))
            print("bitrate")
            print(Float(bitrate))
            let encoder = SDAVAssetExportSession(asset: anAsset)
            encoder?.shouldOptimizeForNetworkUse = true
     
            encoder?.timeRange = timeRange
            encoder?.outputFileType = AVFileType.mp4.rawValue
            encoder?.outputURL = aOutputURL
            //960 X 540 , 1280 * 720 , 1920*1080 // size reduce parameter
            encoder?.videoSettings = [
                AVVideoCodecKey: AVVideoCodecType.h264,
                AVVideoWidthKey:  landscap ? NSNumber(value:1280) : NSNumber(value:720) ,
                AVVideoHeightKey:  landscap ? NSNumber(value:720) : NSNumber(value:1280),
                AVVideoCompressionPropertiesKey: [
                    AVVideoAverageBitRateKey: NSNumber(value: bitrate),
                    AVVideoProfileLevelKey: AVVideoProfileLevelH264High40
                ]
            ]
            encoder?.audioSettings = [
                AVFormatIDKey: NSNumber(value: kAudioFormatMPEG4AAC),
                AVNumberOfChannelsKey: NSNumber(value: 2),
                AVSampleRateKey: NSNumber(value: 44100),
                AVEncoderBitRateKey: NSNumber(value: 128000)
            ]
            
            encoder?.exportAsynchronously(completionHandler: {
                if encoder?.status == .completed {
                    print("Video export succeeded")
                    DispatchQueue.main.async {
                        appDelegate.hideLoader()
                        //NotificationCenter.default.post(name: Notification.Name("getMediaEffect"), object: "3")
                        //self.sendCompletion?(UIImage(), aOutputURL)
                        let text = "Original video-  \(inputURL.verboseFileSizeInMB()) \n and Compressed video \(aOutputURL.verboseFileSizeInMB()) "
                        let alertController = UIAlertController.init(title: "Compressed!!", message: text , preferredStyle: .alert)
                        alertController.addAction(UIAlertAction.init(title: "share to server!", style: .default, handler: { (action) in
                            // Completion block
                            NotificationCenter.default.post(name: Notification.Name("getMediaEffect"), object: "3")
                            self.sendCompletion?(UIImage(), aOutputURL)
                        }))
                        alertController.addAction(UIAlertAction.init(title: "Save", style: .default, handler: { (action) in
                            // Completion block
                            DispatchQueue.main.async {
                                appDelegate.hideLoader()
                                if let videoURL = aOutputURL as? URL{
                                    self.shareVideo(aUrl:videoURL )
                                }
                            }
                        }))
                        alertController.addAction(UIAlertAction.init(title: "cancel!", style: .default, handler: { (action) in
                        }))
                        self.present(alertController, animated: true, completion: nil)
                    }
                    
                } else if encoder?.status == .cancelled {
                    print("Video export cancelled")
                    DispatchQueue.main.async {
                        appDelegate.hideLoader()
                        self.view.makeToast("error_something_went_wrong".localized)
                    }
                } else {
                    print("Video export failed with error: \(encoder!.error.localizedDescription) ")
                    DispatchQueue.main.async {
                        appDelegate.hideLoader()
                        self.view.makeToast("error_something_went_wrong".localized)
                    }
                }
            })
        }
    
     func isLandScapVideo(afileURL: URL) -> Bool{
            let resolution = self.resolutionForLocalVideo(url: afileURL)
            guard let width = resolution?.width, let height = resolution?.height else {
                return false
            }
            if abs(width) > abs(height){
                //landscap
                return true
            }else{
                //potrait
                return false
            }
        }
    extension URL {
        func verboseFileSizeInMB() -> Float{
            let p = self.path
            
            let attr = try? FileManager.default.attributesOfItem(atPath: p)
            
            if let attr = attr {
                let fileSize = Float(attr[FileAttributeKey.size] as! UInt64) / (1024.0 * 1024.0)
                print(String(format: "FILE SIZE: %.2f MB", fileSize))
                return fileSize
            } else {
                return Float.zero
            }
        }
    }
    
    
    //Extra At SDAVAssetExportSession library changes below at m file:(changes as per your requirement)
         ——   CGAffineTransform matrix = CGAffineTransformMakeTranslation(transx / xratio, transy / yratio - transform.ty);
    
     ——//fix Orientation - 1
        UIImageOrientation videoAssetOrientation = UIImageOrientationUp;
        BOOL isVideoAssetPortrait = NO;
        CGAffineTransform videoTransform = videoTrack.preferredTransform;
        if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
            videoAssetOrientation = UIImageOrientationRight;
            isVideoAssetPortrait = YES;
        }
        if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
            videoAssetOrientation =  UIImageOrientationLeft;
            isVideoAssetPortrait = YES;
        }
        if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
            videoAssetOrientation =  UIImageOrientationUp;
        }
        if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
            videoAssetOrientation = UIImageOrientationDown;
        }
       // [passThroughLayer setTransform:transform atTime:kCMTimeZero];
        if ((videoAssetOrientation = UIImageOrientationDown) || (videoAssetOrientation = UIImageOrientationLeft)){
            [passThroughLayer setTransform:videoTrack.preferredTransform atTime:kCMTimeZero];
        }else{
            [passThroughLayer setTransform:transform atTime:kCMTimeZero];
        }