Search code examples
iosobjective-cavfoundationavcapturesessionavcapturemoviefileoutput

IOS adding UIProgressView to AVFoundation AVCaptureMovieFileOutput


I am using AVCaptureMovieFileOutput to record videos and I want to add a UIProgressView to represent how much time there is left before the video stops recording.

I set a max duration of 15 seconds:

CMTime maxDuration = CMTimeMakeWithSeconds(15, 50);
[[self movieFileOutput] setMaxRecordedDuration:maxDuration];

I can't seem to find if AVCaptureMovieFileOutput has a callback for when the video is recording or for when recording begins. My question is, how can I get updates on the progress of the recording? Or if this isn't something that is available, how can I tell when recording begins in order to start a timer?


Solution

  • Here is how I was able to add a UIProgressView

    recording is a property of AVCaptureFileOutput which is extended by AVCaptureMovieFileOutput

    I have a variable movieFileOutput of type AVCaptureMovieFileOutput that I am using to capture data to a QuickTime movie.

    @property (nonatomic) AVCaptureMovieFileOutput *movieFileOutput;
    

    I added an observer to the recording property to detect a change in recording.

    [self addObserver:self
               forKeyPath:@"movieFileOutput.recording"
                  options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew)
                  context:RecordingContext];
    

    Then in the callback method:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
    

    I created a while loop to be executed in the background, then I made sure to dispatch updates to the view on the main thread like this:

        dispatch_async([self sessionQueue], ^{ // Background task started
            // While the movie is recording, update the progress bar
            while ([[self movieFileOutput] isRecording]) {
                double duration = CMTimeGetSeconds([[self movieFileOutput] recordedDuration]);
                double time = CMTimeGetSeconds([[self movieFileOutput] maxRecordedDuration]);
                CGFloat progress = (CGFloat) (duration / time);
                dispatch_async(dispatch_get_main_queue(), ^{ // Here I dispatch to main queue and update the progress view.
                    [self.progressView setProgress:progress animated:YES];
                });
            }
        });