So, when I started understanding about the AVFoundation Framework, initially, it was a bit difficult to understand, but when I started to apply various methods in real-time, it was so easy to understand.
Let’s have a look at the AVFoundation framework in-detail.
What is AVFoundation?
AVFoundation is a time-based full-featured framework widely used with Swift and Objective-C interfaces that are offering a high level of services to work with time-based audiovisual media on iOS, macOS, watchOS and tvOS. AVFoundtation, let’s you create, play and edit QuickTime movies, HLS streams, and MPEG-4 files incorporating powerful media functionality.
AVfoundation framework is used for detailed level time-based audiovisual data, where you can capture, process, edit, and apply a filter on videos or Audio files.
I am using this functionality in one of my projects, where the users can Merge video over the video, Video over the image, Audio over the image.
Trim Video with AVFoundation and Swift
Getting Started with Code
Nowadays, video trimming is essential functionality, and one of the libraries called UIImagePikerController is already providing this functionality. In this blog, we will be going to have a look at how video files will trim and how we can set the quality of the video.
Objective C #import < AVFoundation/AVFoundation.h > Swift @import AVfundation
Import AVFoundation framework in your usable class
Objective C AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URLVideo options:nil]; Swift var asset: AVURLAsset = AVURLAsset(URL: self.url)
AVURLAsset Object is used to get metadata of the Video file like Tracks name, Composer info, Video length, and Video Duration.
Objective C AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality]; Swift var exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)
AVAssetExportSession object fetches the content from the asset object and provides the output of the form described by a specified export preset.
Here we will be required to provide inputs like:
Output URL: Where edited video file will be stored
File Type: Final video type (.mov, .Mp4)
Time Range: Start time and End time for where to trim the video
Objective C NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *outputURL = paths[0]; NSFileManager *manager = [NSFileManager defaultManager]; [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil]; outputURL = [outputURL stringByAppendingPathComponent:@"output.mp4"]; // Remove Existing File [manager removeItemAtPath:outputURL error:nil]; Swift outputURL = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] let fileManager = NSFileManager.defaultManager() fileManager.createDirectoryAtPath(outputURL, withIntermediateDirectories: false, attributes: nil, error: nil) outputURL = outputURL.appendingPathComponent(“output.mp4”)
Get the destination path using NSFileManager
exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
And give that path to exportSession Output URL
exportSession.shouldOptimizeForNetworkUse = YES; exportSession.outputFileType = AVFileTypeQuickTimeMovie;
Set the OptimizeForNetworkUse to Yes and File type as per your specific requirements.
CMTime startTime = CMTimeMake((int)(floor(0 * 100)), 100); CMTime stopTime = CMTimeMake((int)(ceil(CMTimeGetSeconds(videoToTrimSecond) * 100)), 100); CMTimeRange range = CMTimeRangeFromTimeToTime(startTime, stopTime); exportSession.timeRange = range;
Get the Start time and End time in the form of CMTime and Create CMTimeRange set range input to exportSession
Objective C [exportSession exportAsynchronouslyWithCompletionHandler:^(void) { NSLog(@"export did finish..."); [MBProgressHUD hideHUDForView:self.view animated:true]; if (compressionEncoder.status == AVAssetExportSessionStatusCompleted) { NSURL *outputURL = exportSession.outputURL; } else { NSLog(@"%li", (long)compressionEncoder.status); NSLog(@"%@", compressionEncoder.error); } }]; Swift exportSession.exportAsynchronouslyWithCompletionHandler({ switch exportSession.status { case .failed: print("Export failed: \(exportSession.error != nil ? exportSession.error!.localizedDescription : "No Error Info")") case .cancelled: print("Export canceled") case .completed: resultClosure(finalOutputUrl!) default: break } })
Once you have initialized an export session with the asset that contains the source media, the export preset name and the output file type, you can start the export running by invoking exportAsynchronouslyWithCompletionHandler:
Once the exporting process will finish, it will return the output with completed or failed Status.
You can get the output URL path from the exportSession.outputURL
Sometimes exporting process will take lots of time to give the output, so we need to show some progress of exporting video to the user so the user can wait until the process gets complete
Let’s add a progress bar to the process. We will show progress using the MBProgresHUD
Objective C NSTimer exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay:) userInfo:nil repeats:YES]; MBProgressHUD *Progresshud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; Progresshud.mode = MBProgressHUDModeAnnularDeterminate; Swift let exportProgressBarTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateExportDisplay(_:)), userInfo: nil, repeats: true) let Progresshud = MBProgressHUD.showAdded(to: view, animated: true) Progresshud?.mode = MBProgressHUDModeAnnularDeterminate
- First, initialize NStimer Object to call updateExportDisplay with 1 second time interval
- Second, Initialize the MBProgressHUD object to show a progress bar
Objective c -(void)updateExportDisplay:(NSTimer *)timer { Progresshud.progress = exportSession.progress; Progresshud.label.text = [NSString stringWithFormat:@"%.0f%%",exporter.progress*100]; } Swift func updateExportDisplay(_ timer: Timer?) { Progresshud.progress = exportSession.progress Progresshud.label.text = String(format: "%.0f%%", exporter.progress * 100) }
Here updateExportDisplay Method will call every 1second, and the method will get Progress from the exportSession.
I hope your purpose of landing on this page is served. We’ve seen in detail how to Trim Video as per your UI requirements using the Advance AVfoundation Framework APIs.
Now all you are required to do is apply the Client’s fancy design and as your main Logic is already ready.
Happy Coding!