{"id":11585,"date":"2020-02-05T12:46:27","date_gmt":"2020-02-05T12:46:27","guid":{"rendered":"https:\/\/www.bacancytechnology.com\/blog\/?p=11585"},"modified":"2024-03-04T05:14:38","modified_gmt":"2024-03-04T05:14:38","slug":"avfoundation-framework-a-hands-on-guideline-to-trim-the-video","status":"publish","type":"post","link":"https:\/\/www.bacancytechnology.com\/blog\/avfoundation-framework-to-trim-the-video","title":{"rendered":"AVFoundation Framework: A Hands-on Guideline to Trim the Video"},"content":{"rendered":"<p>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.<\/p>\n<p><strong>Let\u2019s have a look at the AVFoundation framework in-detail.<\/strong><\/p>\n<h2>What is AVFoundation?<\/h2>\n<p>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\u2019s you create, play and edit QuickTime movies, HLS streams, and MPEG-4 files incorporating powerful media functionality.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<h3>Trim Video with AVFoundation and Swift<\/h3>\n<p><strong>Getting Started with Code<\/strong><\/p>\n<p>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. <\/p>\n<pre>\r\nObjective C\r\n#import < AVFoundation\/AVFoundation.h >\r\nSwift\r\n@import AVfundation\r\n<\/pre>\n<p>Import AVFoundation framework in your usable class <\/p>\n<pre>\r\nObjective C\r\n AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URLVideo options:nil];\r\n\r\nSwift \r\nvar asset: AVURLAsset = AVURLAsset(URL: self.url)\r\n<\/pre>\n<p>AVURLAsset Object is used to get metadata of the Video file like Tracks name, Composer info, Video length, and Video Duration. <\/p>\n<pre>\r\nObjective C\r\n AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];\r\n\r\nSwift\r\nvar exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)\r\n<\/pre>\n<p>AVAssetExportSession object fetches the content from the asset object and provides the output of the form described by a specified export preset.<\/p>\n<p><strong>Here we will be required to provide inputs like: <\/strong><\/p>\n<p><strong>Output URL: <\/strong> Where edited video file will be stored <\/p>\n<p><strong>File Type:<\/strong> Final video type (.mov, .Mp4) <\/p>\n<p><strong>Time Range:<\/strong>  Start time and End time for where to trim the video <\/p>\n<pre>\r\nObjective C\r\n\r\nNSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\r\n    NSString *outputURL = paths[0];\r\n    NSFileManager *manager = [NSFileManager defaultManager];\r\n    [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil];\r\n    outputURL = [outputURL stringByAppendingPathComponent:@\"output.mp4\"];\r\n    \/\/ Remove Existing File\r\n    [manager removeItemAtPath:outputURL error:nil];\r\n\r\nSwift\r\n         \r\n        outputURL = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]\r\n       let fileManager =  NSFileManager.defaultManager()\r\nfileManager.createDirectoryAtPath(outputURL, withIntermediateDirectories: false, attributes: nil, error: nil)\r\n outputURL = outputURL.appendingPathComponent(\u201coutput.mp4\u201d)\r\n<\/pre>\n<p>Get the destination path using NSFileManager <\/p>\n<pre> exportSession.outputURL = [NSURL fileURLWithPath:outputURL];<\/pre>\n<p>And give that path to exportSession Output URL<\/p>\n<pre>\r\nexportSession.shouldOptimizeForNetworkUse = YES;\r\nexportSession.outputFileType = AVFileTypeQuickTimeMovie;\r\n<\/pre>\n<p>Set the OptimizeForNetworkUse to Yes and File type as per your specific requirements. <\/p>\n<pre>\r\nCMTime startTime = CMTimeMake((int)(floor(0 * 100)), 100);\r\n CMTime stopTime = CMTimeMake((int)(ceil(CMTimeGetSeconds(videoToTrimSecond) * 100)), 100);\r\n  CMTimeRange range = CMTimeRangeFromTimeToTime(startTime, stopTime);\r\n   \r\n  exportSession.timeRange = range;\r\n<\/pre>\n<p>Get the Start time and End time in the form of CMTime and Create CMTimeRange set range input to exportSession <\/p>\n<pre>\r\nObjective C\r\n [exportSession exportAsynchronouslyWithCompletionHandler:^(void)\r\n     {\r\n             NSLog(@\"export did finish...\");\r\n            \r\n              [MBProgressHUD hideHUDForView:self.view animated:true];\r\n             if (compressionEncoder.status == AVAssetExportSessionStatusCompleted) {\r\n                 NSURL *outputURL = exportSession.outputURL;\r\n              \r\n                 \r\n             } else {\r\n                 NSLog(@\"%li\", (long)compressionEncoder.status);\r\n                  NSLog(@\"%@\", compressionEncoder.error);\r\n             }\r\n\r\n    }];\r\n\r\nSwift\r\nexportSession.exportAsynchronouslyWithCompletionHandler({\r\n     switch exportSession.status {\r\n        case .failed:\r\n            print(\"Export failed: \\(exportSession.error != nil ? exportSession.error!.localizedDescription : \"No Error Info\")\")\r\n        case .cancelled:\r\n            print(\"Export canceled\")\r\n        case .completed:\r\n            resultClosure(finalOutputUrl!)\r\n        default:\r\n            break\r\n        }\r\n\r\n })\r\n<\/pre>\n<p>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:<\/p>\n<p>Once the exporting process will finish, it will return the output with completed or failed Status.<\/p>\n<p>You can get the output URL path from the exportSession.outputURL <\/p>\n<p>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 <\/p>\n<p>Let\u2019s add a progress bar to the process. We will show progress using the MBProgresHUD <\/p>\n<pre>\r\nObjective C       \r\n\r\nNSTimer   exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay:) userInfo:nil repeats:YES];\r\n\r\nMBProgressHUD    *Progresshud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];\r\n Progresshud.mode = MBProgressHUDModeAnnularDeterminate;\r\n\r\nSwift\r\n\r\nlet exportProgressBarTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateExportDisplay(_:)), userInfo: nil, repeats: true)\r\n\r\nlet Progresshud = MBProgressHUD.showAdded(to: view, animated: true)\r\nProgresshud?.mode = MBProgressHUDModeAnnularDeterminate\r\n\r\n<\/pre>\n<ul class=\"bullet\">\n<li>First, initialize NStimer Object to call updateExportDisplay with 1 second time interval <\/li>\n<li>Second, Initialize the MBProgressHUD object to show a progress bar<\/li>\n<\/ul>\n<pre>\r\nObjective c\r\n-(void)updateExportDisplay:(NSTimer *)timer {\r\n    \r\n    Progresshud.progress = exportSession.progress;\r\n    Progresshud.label.text = [NSString stringWithFormat:@\"%.0f%%\",exporter.progress*100];\r\n    \r\n    \r\n} \r\n\r\nSwift\r\nfunc updateExportDisplay(_ timer: Timer?) {\r\n\r\n    Progresshud.progress = exportSession.progress\r\n    Progresshud.label.text = String(format: \"%.0f%%\", exporter.progress * 100)\r\n\r\n\r\n}\r\n\r\n\r\n<\/pre>\n<p>Here updateExportDisplay Method will call every 1second, and the method will get Progress from the exportSession.<\/p>\n<p>I hope your purpose of landing on this page is served. We\u2019ve seen in detail how to Trim Video as per your UI requirements using the Advance AVfoundation Framework APIs.<\/p>\n<p>Now all you are required to do is apply the Client\u2019s fancy design and as your main Logic is already ready.<\/p>\n<p>Happy Coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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\u2019s have a look at the AVFoundation framework in-detail. What is AVFoundation? AVFoundation is a time-based full-featured framework widely used with Swift [&hellip;]<\/p>\n","protected":false},"author":35,"featured_media":11590,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_lmt_disableupdate":"no","_lmt_disable":"","footnotes":""},"categories":[212,1364],"tags":[],"coauthors":[1596],"class_list":["post-11585","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ios","category-application-development"],"acf":[],"modified_by":"Chandresh Patel","_links":{"self":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts\/11585","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/comments?post=11585"}],"version-history":[{"count":0,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts\/11585\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/media\/11590"}],"wp:attachment":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/media?parent=11585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/categories?post=11585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/tags?post=11585"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/coauthors?post=11585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}