I\'m following the only answer this has on SO -
Switch cameras with avcapturesession
However cameraWithPosition does not seem to work. Deprecated?
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];
}
}
}
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
}
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.