Switch front/back camera with AVCaptureSession

前端 未结 5 443
时光取名叫无心
时光取名叫无心 2020-12-29 10:01

I\'m following the only answer this has on SO -

Switch cameras with avcapturesession

However cameraWithPosition does not seem to work. Deprecated?

         


        
相关标签:
5条回答
  • 2020-12-29 10:08

    Here is an example for using the switch with a video session:

    .h
    
    UIViewController<AVCaptureFileOutputRecordingDelegate>
    
    @property(nonatomic,strong)  AVCaptureSession *CaptureSession;
    @property(nonatomic,strong) AVCaptureMovieFileOutput *MovieFileOutput;
    @property(nonatomic,strong) AVCaptureDeviceInput *VideoInputDevice;
    
    - (void) CameraSetOutputProperties;
    - (AVCaptureDevice *) CameraWithPosition:(AVCaptureDevicePosition) Position;
    

    Then:

    .m
    
    - (void)viewDidLoad {
    
       [super viewDidLoad];
    
       CaptureSession = [[AVCaptureSession alloc] init];
    
       //etc
    
    
    }
    
    - (IBAction)CameraToggle:(id)sender
    {
        if ([[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count] > 1)        //Only do if device has multiple cameras
        {
            NSError *error;
            //AVCaptureDeviceInput *videoInput = [self videoInput];
            AVCaptureDeviceInput *NewVideoInput;
            AVCaptureDevicePosition position = [[VideoInputDevice device] position];
            if (position == AVCaptureDevicePositionBack)
            {
                NewVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionFront] error:&error];
            }
            else if (position == AVCaptureDevicePositionFront)
            {
                NewVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionBack] error:&error];
            }
    
            if (NewVideoInput != nil)
            {
                [CaptureSession beginConfiguration];
                [CaptureSession removeInput:VideoInputDevice];
                if ([CaptureSession canAddInput:NewVideoInput])
                {
                    [CaptureSession addInput:NewVideoInput];
                    VideoInputDevice = NewVideoInput;
                }
                else
                {
                    [CaptureSession addInput:VideoInputDevice];
                }
    
                //Set the connection properties again
                [self CameraSetOutputProperties];
    
    
                [CaptureSession commitConfiguration];
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-29 10:11

    What you need to do is reconfigure your AVCaptureSession

    Here is what i'm using:

    // note that `AVCaptureSession * session`
    //
    if(session)
    {
        [session beginConfiguration];
    
        AVCaptureInput *currentCameraInput = [session.inputs objectAtIndex:0];
    
        [session removeInput:currentCameraInput];
    
        AVCaptureDevice *newCamera = nil;
    
        if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack)
        {
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
        }
        else
        {
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
        }
    
        NSError *err = nil;
    
        AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&err];
    
        if(!newVideoInput || err)
        {
            NSLog(@"Error creating capture device input: %@", err.localizedDescription);
        }
        else
        {
            [session addInput:newVideoInput];
        }
    
        [session commitConfiguration];
    }
    
    // make sure you have this method in your class
    //
    - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
    {
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    
        for (AVCaptureDevice *device in devices)
        {
            if ([device position] == position)
                return device;
        }
        return nil;
    }
    
    0 讨论(0)
  • 2020-12-29 10:14

    Code update for Swift 4.2

    /// Swap camera and reconfigures camera session with new input
    fileprivate func swapCamera() {
    
        // Get current input
        guard let input = captureSession.inputs[0] as? AVCaptureDeviceInput else { return }
    
        // Begin new session configuration and defer commit
        captureSession.beginConfiguration()
        defer { captureSession.commitConfiguration() }
    
        // Create new capture device
        var newDevice: AVCaptureDevice?
        if input.device.position == .back {
            newDevice = captureDevice(with: .front)
        } else {
            newDevice = captureDevice(with: .back)
        }
    
        // Create new capture input
        var deviceInput: AVCaptureDeviceInput!
        do {
            deviceInput = try AVCaptureDeviceInput(device: newDevice!)
        } catch let error {
            print(error.localizedDescription)
            return
        }
    
        // Swap capture device inputs
        captureSession.removeInput(input)
        captureSession.addInput(deviceInput)
    }
    
    /// Create new capture device with requested position
    fileprivate func captureDevice(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
    
        let devices = AVCaptureDevice.DiscoverySession(deviceTypes: [ .builtInWideAngleCamera, .builtInMicrophone, .builtInDualCamera, .builtInTelephotoCamera ], mediaType: AVMediaType.video, position: .unspecified).devices
    
        //if let devices = devices {
            for device in devices {
                if device.position == position {
                    return device
                }
            }
        //}
    
        return nil
    }
    
    0 讨论(0)
  • 2020-12-29 10:24

    In Swift 3.0

    /// Swap camera and reconfigures camera session with new input
    fileprivate func swapCamera() {
    
        // Get current input
        guard let input = cameraSession.inputs[0] as? AVCaptureDeviceInput else { return }
    
        // Begin new session configuration and defer commit
        cameraSession.beginConfiguration()
        defer { cameraSession.commitConfiguration() }
    
        // Create new capture device
        var newDevice: AVCaptureDevice?
        if input.device.position == .back {
            newDevice = captureDevice(with: .front)
        } else {
            newDevice = captureDevice(with: .back)
        }
    
        // Create new capture input
        var deviceInput: AVCaptureDeviceInput!
        do {
            deviceInput = try AVCaptureDeviceInput(device: newDevice)
        } catch let error {
            print(error.localizedDescription)
            return
        }
    
        // Swap capture device inputs
        cameraSession.removeInput(input)
        cameraSession.addInput(deviceInput)
    }
    
    /// Create new capture device with requested position
    fileprivate func captureDevice(with position: AVCaptureDevicePosition) -> AVCaptureDevice? {
    
        let devices = AVCaptureDeviceDiscoverySession(deviceTypes: [ .builtInWideAngleCamera, .builtInMicrophone, .builtInDualCamera, .builtInTelephotoCamera ], mediaType: AVMediaTypeVideo, position: .unspecified).devices
    
        if let devices = devices {
            for device in devices {
                if device.position == position {
                    return device
                }
            }
        }
    
        return nil
    }
    
    0 讨论(0)
  • 2020-12-29 10:29

    Code update for Swift 5

    extension CameraManager {
        func switchCamera() {
            captureSession.beginConfiguration()
            defer {captureSession.commitConfiguration()}
    
            let nextPosition = ((currentCameraInput as? AVCaptureDeviceInput)?.device.position == .front) ? AVCaptureDevice.Position.back : .front
    
            if let currentCameraInput = currentCameraInput {
                captureSession.removeInput(currentCameraInput)
            }
    
            if let newCamera = cameraDevice(position: nextPosition),
                let newVideoInput: AVCaptureDeviceInput = try? AVCaptureDeviceInput(device: newCamera),
                captureSession.canAddInput(newVideoInput) {
    
                captureSession.addInput(newVideoInput)
                currentCameraInput = newVideoInput
    
                videoDataOutput.connection(with: .video)?.videoOrientation = .portrait
                videoDataOutput.connection(with: .video)?.automaticallyAdjustsVideoMirroring = false
                videoDataOutput.connection(with: .video)?.isVideoMirrored = nextPosition == .front
            }
        }
    
        private func cameraDevice(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
            let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
            for device in discoverySession.devices where device.position == position {
                return device
            }
    
            return nil
        }
    }
    

    And full code of camera using AVCaptureSession is this gist.

    0 讨论(0)
提交回复
热议问题