-->

Zooming while capturing video using AVCapture in i

2020-03-08 00:01发布

问题:

I am using AVCapture to capture video and save it. But I need to provide zooming option like pinch to zoom or through a zoom button. Also video should be saved in exactly in same manner in which it is being displayed, I mean when zoomed in, it should be saved zoomed. Any help, Link is appreciated. My code for setting up AVCapture session is:

- (void)setupAVCapture{
session = [[AVCaptureSession alloc] init];
session.automaticallyConfiguresApplicationAudioSession=YES;
[session beginConfiguration];
session.sessionPreset = AVCaptureSessionPresetMedium;
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
captureVideoPreviewLayer.frame = self.view.bounds;

[self.view.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
    // Handle the error appropriately.
    NSLog(@"ERROR: trying to open camera: %@", error);
}
[session addInput:input];

movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];

[session addOutput:movieFileOutput];
[session commitConfiguration];
[session startRunning];

 }

回答1:

I faced the same problem also, and I have solved it using these two steps:

  1. Add a PinchGestureRecognizer event something like that in your Camera Preview View Controller

    - (IBAction)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer{
    
    if([gestureRecognizer isMemberOfClass:[UIPinchGestureRecognizer class]])
    {
    
            effectiveScale = beginGestureScale * ((UIPinchGestureRecognizer *)gestureRecognizer).scale;
            if (effectiveScale < 1.0)
                effectiveScale = 1.0;
            CGFloat maxScaleAndCropFactor = [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor];
            if (effectiveScale > maxScaleAndCropFactor)
                effectiveScale = maxScaleAndCropFactor;
            [CATransaction begin];
            [CATransaction setAnimationDuration:.025];
            [self.previewView.layer setAffineTransform:CGAffineTransformMakeScale(effectiveScale, effectiveScale)];
            [CATransaction commit];
    
        if ([[self videoDevice] lockForConfiguration:nil]) {
            [[self videoDevice] setVideoZoomFactor:effectiveScale];
            [[self videoDevice] unlockForConfiguration];
        }}}}
    

** Note that the key method for persisting the zoom level for video device is [device setVideoZoomFactor:]

2- In the IBAction of the Record Button , add this code to capture the video ( recording ) then to save the recorded video in the a certain path with certain name

- (IBAction)recordButtonClicked:(id)sender {

dispatch_async([self sessionQueue], ^{
    if (![[self movieFileOutput] isRecording])
    {
        [self setLockInterfaceRotation:YES];

        if ([[UIDevice currentDevice] isMultitaskingSupported])
        {
            // Setup background task. This is needed because the captureOutput:didFinishRecordingToOutputFileAtURL: callback is not received until the app returns to the foreground unless you request background execution time. This also ensures that there will be time to write the file to the assets library when the app is backgrounded. To conclude this background execution, -endBackgroundTask is called in -recorder:recordingDidFinishToOutputFileURL:error: after the recorded file has been saved.
            [self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]];
        }

        // Update the orientation on the movie file output video connection before starting recording.
        // Start recording to a temporary file.
        NSString *outputFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[@"movie" stringByAppendingPathExtension:@"mov"]];
        [[self movieFileOutput] startRecordingToOutputFileURL:[NSURL fileURLWithPath:outputFilePath] recordingDelegate:self];
    }
    else
    {

        [[self movieFileOutput] stopRecording];

    }
});
}

I hope that helps you



回答2:

Add UIPinchGestureRecognizer object to your and handle callback like this:

- (void) zoomPinchGestureRecognizerAction: (UIPinchGestureRecognizer *) sender {
    static CGFloat initialVideoZoomFactor = 0;

    if (sender.state == UIGestureRecognizerStateBegan) {

        initialVideoZoomFactor = _captureDevice.videoZoomFactor;

    } else {

        CGFloat scale = MIN(MAX(1, initialVideoZoomFactor * sender.scale), 4);

        [CATransaction begin];
        [CATransaction setAnimationDuration: 0.01];
        _previewLayer.affineTransform = CGAffineTransformMakeScale(scale, scale);
        [CATransaction commit];

        if ([_captureDevice lockForConfiguration: nil] == YES) {
            _captureDevice.videoZoomFactor = scale;
            [_captureDevice unlockForConfiguration];
        }
    }
}