Swift - Compressing Video Files

Swift - Compressing video files

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

How to compress a video in swift?

I have looked at your code. Actually, you are compressing video in medium quality which will be around the same as the original video which you have. So, you have to change presetName in export session initialization as follow:

exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetLowQuality)

You can pass AVAssetExportPresetMediumQuality, So it's could be compressed as you expect.

There is the following list of format available to compress video.

1. Available from iOS 11.0

  • AVAssetExportPresetHEVCHighestQuality
  • AVAssetExportPresetHEVC1920x1080
  • AVAssetExportPresetHEVC3840x2160

2. Available from iOS 4.0

  • AVAssetExportPresetLowQuality
  • AVAssetExportPresetMediumQuality
  • AVAssetExportPresetHighestQuality
  • AVAssetExportPreset640x480
  • AVAssetExportPreset960x540
  • AVAssetExportPreset1280x720
  • AVAssetExportPreset1920x1080
  • AVAssetExportPreset3840x2160
  • AVAssetExportPresetAppleM4A

You can use above all format to compress your video based on your requirements.
I hope this will help you.

compressing a video in iOS

I have figured it out, thanks to this question (Swift version): IOS Video Compression Swift iOS 8 corrupt video file

I have the objective C version. Here is the method:

 - (void)compressVideo:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
handler:(void (^)(AVAssetExportSession*))completion {
AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:urlAsset presetName:AVAssetExportPresetMediumQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
completion(exportSession);
}];
}

And calling the method:

NSURL* uploadURL = [NSURL fileURLWithPath:
[NSTemporaryDirectory() stringByAppendingPathComponent:@"temporaryPreview.mov"]];

[self compressVideo:self.movieURL outputURL:uploadURL handler:^(AVAssetExportSession *completion) {
if (completion.status == AVAssetExportSessionStatusCompleted) {
NSData *newDataForUpload = [NSData dataWithContentsOfURL:uploadURL];
NSLog(@"Size of new Video after compression is (bytes):%d",[newDataForUpload length]);
}
}];

This reduced the file size of my videos from 32 MB to 1.5 MB.

reduce video size in swift/iOS to upload to server

Try this answer for compress video. According to jojaba's answer:

If you are wanting to compress the video for remote sharing and to
keep the original quality for local storage on the iPhone, you should
look into AVAssetExportSession or AVAssetWriter.

Compress Video Without Low Quality

This approach is as per Objective-C though.

You should also consider reading on how iOS manages Assets.

IOS Video Compression Swift iOS 8 corrupt video file

This answer has been completely rewritten and annotated to support Swift 4.0. Keep in mind that changing the AVFileType and presetName values allows you to tweak the final output in terms of size and quality.

import AVFoundation

extension ViewController: AVCaptureFileOutputRecordingDelegate {
// Delegate function has been updated
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
// This code just exists for getting the before size. You can remove it from production code
do {
let data = try Data(contentsOf: outputFileURL)
print("File size before compression: \(Double(data.count / 1048576)) mb")
} catch {
print("Error: \(error)")
}
// This line creates a generic filename based on UUID, but you may want to use your own
// The extension must match with the AVFileType enum
let path = NSTemporaryDirectory() + UUID().uuidString + ".m4v"
let outputURL = URL.init(fileURLWithPath: path)
let urlAsset = AVURLAsset(url: outputURL)
// You can change the presetName value to obtain different results
if let exportSession = AVAssetExportSession(asset: urlAsset,
presetName: AVAssetExportPresetMediumQuality) {
exportSession.outputURL = outputURL
// Changing the AVFileType enum gives you different options with
// varying size and quality. Just ensure that the file extension
// aligns with your choice
exportSession.outputFileType = AVFileType.mov
exportSession.exportAsynchronously {
switch exportSession.status {
case .unknown: break
case .waiting: break
case .exporting: break
case .completed:
// This code only exists to provide the file size after compression. Should remove this from production code
do {
let data = try Data(contentsOf: outputFileURL)
print("File size after compression: \(Double(data.count / 1048576)) mb")
} catch {
print("Error: \(error)")
}
case .failed: break
case .cancelled: break
}
}
}
}
}

Below is the original answer as written for Swift 3.0:

extension ViewController: 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)
}
}
}

Swift iOS -How to compress stored embedded video file size?

I recorded my app's background video on an iPhone 7+ using FilmicPro. Everything was recorded in 4K. As the question states the file size was very high after it was uploaded to iTunesConnect. What I did to get around the issue was convert my 4K video to 1080P. I used FCPX and the conversion took a few minutes. The quality looked exactly the same.

Here's the YouTube video I followed on how to create the conversion. It's very easy to follow and is less then 5 minutes:

YouTube -Convert video from 4K to 1080P

swift video compression removes sound when video length gets to a certain amount

I found the solution on my own. I've changed the video format to .mov and it worked.



Related Topics



Leave a reply



Submit