Swift - Compressing video files
20,338
Solution 1
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)
}
}
}
Solution 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)
}
}
Author by
Roduck Nickes
Updated on July 09, 2022Comments
-
Roduck Nickes almost 2 years
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?
-
Roduck Nickes over 7 yearsI guess since my class name is
class PreviewVideoViewController: UIViewController {
I should replace yourMyViewController
withPreviewVideoViewController
? But I do get 3 error messages: s22.postimg.org/p8ps48lm9/… -
CodeBender over 7 years@RoduckNickes Is your app in Swift 2.2?
-
Roduck Nickes over 7 yearsIt says
Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1) Target: x86_64-apple-macosx10.9
when I runxcrun swift -version
in Terminal. -
CodeBender over 7 years@RoduckNickes Updated with a 2.2 answer, since your errors are indicating that you are not writing for 3.0. Let me know if that does not work for you.
-
vaibhav almost 7 yearsno sound in video i found when i compress video using this code..?
-
Martin over 6 years@vaibhav: is there sound in your video before the compression? Did you record it properly with an audio input source set?
-
vaibhav over 6 yearsits done by adding single line in code
session.sessionPreset = AVCaptureSessionPresetMedium
and the sound turns off when the video recorded time is greater then 10 sec, its corrected by addingself.movieOutput.movieFragmentInterval = kCMTimeInvalid
line of code. -
Sachin Kishore over 5 yearsError: Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_0102.MP4” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/mobile/Media/DCIM/100APPLE/IMG_0102.MP4, NSUnderlyingError=0x1030b70f0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}} file:///private/var/mobile/Containers/Data/Application/B38F4E96-43B1-449C-A3F1-A99960E52BC3/tmp/FEBC7046-D7B8-4A86-B889-92D2CDFA8879.mp4 File size after compression: 0.0 mb
-
Mahesh Joya over 3 yearsCheck if anyone have issue with tranfom or any other issue in SDK: github.com/YaoSu/SDAVAssetExportSession
-
ScripterKiddo almost 2 yearsI used this code but after the video length passed a certain unknown amount sound from the video is removed