Progress bar for AVAssetExportSession

后端 未结 4 602
遇见更好的自我
遇见更好的自我 2021-02-02 11:57

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

相关标签:
4条回答
  • 2021-02-02 12:47

    Use below lines of code.

    AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
    self.exportSession = session;
    
    // 出力先(テンポラリファイル)の設定。
    NSString *filePath = NSTemporaryDirectory();
    filePath = [filePath stringByAppendingPathComponent:@"out.mov"];
    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
    session.outputURL = [NSURL fileURLWithPath:filePath];
    
    // 出力タイプの設定。
    session.outputFileType = AVFileTypeQuickTimeMovie;
    
    // 非同期エクスポートの開始。
    [session exportAsynchronouslyWithCompletionHandler:^{
        if (session.status == AVAssetExportSessionStatusCompleted) {
            // フォトアルバムへの書き込み。
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
            [library writeVideoAtPathToSavedPhotosAlbum:session.outputURL completionBlock:^(NSURL *assetURL, NSError *error){
                if (error) {
                    self.resultLabel.text = [NSString stringWithFormat:@"アセット書き込み失敗\n%@", error];
                } else {
                    self.resultLabel.text = [NSString stringWithFormat:@"完了\n%@", assetURL];
                }
            }];
            [library autorelease];
        } else if (session.status == AVAssetExportSessionStatusCancelled) {
            self.resultLabel.text = @"エクスポート中断";
        } else {
            self.resultLabel.text = [NSString stringWithFormat:@"エクスポート失敗\n%@", session.error];
        }
    }];
    
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        while (session.status == AVAssetExportSessionStatusExporting) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                self.progressView.progress = session.progress;
            });
        }
    });
    

    Reference Link : https://github.com/keijiro/iOS4BookSampleCode/blob/master/3.3.SimpleExport/Classes/SimpleExportViewController.m

    0 讨论(0)
  • 2021-02-02 12:55

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

    }

    0 讨论(0)
  • 2021-02-02 12:56

    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)
    
    0 讨论(0)
  • 2021-02-02 12:59

    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];
        }
    }
    
    0 讨论(0)
提交回复
热议问题