Switch front/back camera with AVCaptureSession
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;
}
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
}
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
}