[SWIFT] 스위프트 - 비디오 파일을 압축
SWIFT스위프트 - 비디오 파일을 압축
해결법
-
1.이 확장 (이 경우 중간에서) 낮은 품질 설정에 수출에 초점을 맞추고 아이폰 OS에 의해 선호 MOV 컨테이너를 통해, MP4 컨테이너를 사용합니다. 이것은 품질의 손실이 발생할 수 있지만 미세 조정에 출력을 작업 할 때 당신은 더 높은 출력 설정과 다른 형식을 실험 할 수 있습니다.
이 확장 (이 경우 중간에서) 낮은 품질 설정에 수출에 초점을 맞추고 아이폰 OS에 의해 선호 MOV 컨테이너를 통해, MP4 컨테이너를 사용합니다. 이것은 품질의 손실이 발생할 수 있지만 미세 조정에 출력을 작업 할 때 당신은 더 높은 출력 설정과 다른 형식을 실험 할 수 있습니다.
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) } } }
-
2.
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) } }
-
3.
//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]; }
from https://stackoverflow.com/questions/40470637/swift-compressing-video-files by cc-by-sa and MIT license
'SWIFT' 카테고리의 다른 글
[SWIFT] 스위프트 4 JSON Codable는 - 반환 값은 때때로 객체, 다른 배열입니다 (0) | 2020.11.06 |
---|---|
[SWIFT] 스위프트 - 재산에 사용자 정의 세터 (0) | 2020.11.06 |
[SWIFT] Alamofire 화재 변수 유형에는 첨자 회원이 없습니다 (0) | 2020.11.06 |
[SWIFT] 사용은 열거 사건을 키워드 예약 (0) | 2020.11.06 |
[SWIFT] 어떻게 MKPointAnnotation에 버튼을 추가하려면? (0) | 2020.11.06 |