Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Progress bar for AVAssetExportSession

I've got an app that exports an AVMutableComposition into a .mov file, and I'd like for the user to see the status of the export with a progress bar the same way that you would if you sent a text message or uploaded a file.

I know how to create a progress bar when I know the duration of a task (such as playing an audio file), but since there's no set duration for the export I'm unsure how to proceed.

I've got an activity indicator currently but it doesn't provide the best user experience.

Does anyone have any pointers?

like image 714
Orpheus Mercury Avatar asked Jun 18 '12 20:06

Orpheus Mercury


3 Answers

I came up with an answer a while back so I'll post it in case it can help someone:

First, in the method in which you call AVAssetExportSession you've got to set up a timer to update your UIProgressView once you've initiated the export:

//`AVAssetExportSession` code here     self.exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay) userInfo:nil repeats:YES]; ... 

Then you need a method to update your display taking into account that the progress property on AVAssetExportSession goes from 0 - 1:

- (void)updateExportDisplay {     self.exportProgressBar.progress = exportSession.progress;     if (self.exportProgressBar.progress > .99) {         [self.exportProgressBarTimer invalidate];     } } 
like image 181
Orpheus Mercury Avatar answered Sep 24 '22 06:09

Orpheus Mercury


Swift 3 example

Using Notification Center to send progress updates to listeners

//`AVAssetExportSession` code above var exportProgressBarTimer = Timer() // initialize timer if #available(iOS 10.0, *) {     exportProgressBarTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in     // Get Progress     let progress = Float((exportSession?.progress)!);     if (progress < 0.99) {        let dict:[String: Float] = ["progress": progress]        NotificationCenter.default.post(name: Notification.Name("ProgressBarPercentage"), object: nil, userInfo: dict)     }   } }  // on exportSession completed exportSession?.exportAsynchronously(completionHandler: {    exportProgressBarTimer.invalidate(); // remove/invalidate timer    if exportSession?.status == AVAssetExportSessionStatus.completed {        // [....Some Completion Code Here]    } }) 

Then setup the notification center listener anywhere you'd like using

NotificationCenter.default.addObserver(self, selector: #selector(self.statusUpdate(_:)), name: NSNotification.Name(rawValue: "ProgressBarPercentage"), object: nil) 
like image 22
andrewoodleyjr Avatar answered Sep 26 '22 06:09

andrewoodleyjr


Same issue i have faced in iOS 8.0, i resolved it using dispatch quee

- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler{

[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];

exportSession2 = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession2.outputURL = outputURL;
exportSession2.outputFileType = AVFileTypeQuickTimeMovie;

[exportSession2 exportAsynchronouslyWithCompletionHandler:^(void)
 {
     handler(exportSession2);
 }];

 dispatch_async(dispatch_get_main_queue(), ^(void){

      self.exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay) userInfo:nil repeats:YES];
 });

}

like image 23
Spydy Avatar answered Sep 26 '22 06:09

Spydy