mindfreek
mindfreek

Reputation: 704

How to get the front camera in Swift?

I am trying to get the front camera with live view. I am able to get the back camera using:

var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

But I can't seem to find how to get the front camera. How can I change the code above to use the front camera?

Upvotes: 30

Views: 32583

Answers (8)

zumzum
zumzum

Reputation: 20138

Latests is:

guard let device = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: .video, position: .front) else {
    return
}

Upvotes: 8

Rafat touqir Rafsun
Rafat touqir Rafsun

Reputation: 2817

Swift 4.1, iOS 10+ and Xcode 9.3 replaces

if let cameraID = AVCaptureDevice.defaultDevice(withDeviceType: AVCaptureDeviceType.builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.front)?.localizedName {
       //cameraID = "Front Camera"
}

with AVCaptureDevice.DiscoverySession implementation

if let cameraID = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.front).devices.first?.localizedName{
        //cameraID = "Front Camera"
} 

Upvotes: 6

jnblanchard
jnblanchard

Reputation: 1200

var captureSession: AVCaptureSession?
var frontDevice: AVCaptureDevice?
var frontInput: AVCaptureInput?

if let frontDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front).devices.first {
  frontInput = try AVCaptureDeviceInput(device: frontDevice)
}

captureSession?.beginConfiguration()
if let front = frontInput, captureSession?.canAddInput(front) == true {
  captureSession?.addInput(front)
}
captureSession?.commitConfiguration()

Upvotes: 2

rickster
rickster

Reputation: 126107

In iOS 10.0 and later, you don't need to iterate through AVCaptureDevice.devices (or devicesWithMediaType) to find a camera by position. (In fact, both of those APIs are deprecated in iOS 10, and don't return the full set of available devices on iPhone 7 Plus, iPhone 8 Plus, or iPhone X.)

If you just need to find a single device based on simple characteristics (like a front-facing camera that can shoot video), just use AVCaptureDevice.defaultDevice(withDeviceType:mediaType:position:). For example:

guard let device = AVCaptureDevice.defaultDevice(
    withDeviceType: .builtInWideAngleCamera,
    mediaType: AVMediaTypeVideo,
    position: .front)
    else { fatalError("no front camera. but don't all iOS 10 devices have them?")

// then use the device: captureSession.addInput(device) or whatever

Really that's all there is to it for most use cases.


There's also AVCaptureDeviceDiscoverySession as a replacement for the old method of iterating through the devices array. However, most of the things you'd usually iterate through the devices array for can be found using the new defaultDevice(withDeviceType:mediaType:position:) method, so you might as well use that and write less code.

The cases where AVCaptureDeviceDiscoverySession is worth using are the less common, more complicated cases: say you want to find all the devices that support a certain frame rate, or use key-value observing to see when the set of available devices changes.


By the way, Apple also has a guide to the iOS 10 / Swift 3 photo capture system and some sample code that both show current best practices for these APIs.

Upvotes: 20

chrissukhram
chrissukhram

Reputation: 2967

Here is a working example from one of my projects to get the front camera. This is in objective-c but proven to work and easy enough to convert to swift.

NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;

for (AVCaptureDevice *device in videoDevices){

    if (device.position == AVCaptureDevicePositionFront){

        captureDevice = device;
        break;
    }
}

And in Swift 3.2+:

if let videoDevices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) {
    var captureDevice: AVCaptureDevice
    for device in videoDevices {
        if let device = device as? AVCaptureDevice {
            if device.position == AVCaptureDevicePosition.front {
                captureDevice = device
                break
            }
        }
    }
}

Upvotes: 23

Amul4608
Amul4608

Reputation: 1448

import AVFoundation
import Foundation


@IBOutlet weak var imageView: UIImageView!
    let captureSession = AVCaptureSession()
    let stillImageOutput = AVCaptureStillImageOutput()
    var previewLayer : AVCaptureVideoPreviewLayer?
    var captureDevice : AVCaptureDevice?
    var Arrdata:[Studentdata] = []
 override func viewDidLoad() {
        super.viewDidLoad()
        captureSession.sessionPreset = AVCaptureSessionPresetHigh
            if let devices = AVCaptureDevice.devices() as? [AVCaptureDevice]
            {
                for device in devices
                {
                    if (device.hasMediaType(AVMediaTypeVideo))
                    {
                        if(device.position == AVCaptureDevicePosition.front)
                        {
                            captureDevice = device
                            if captureDevice != nil
                            {
                                print("Capture device found")
                                beginSession()
                            }
                        }
                    }
                }
            }


    }

func beginSession()
    {
        do
        {
            try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
            stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
            if captureSession.canAddOutput(stillImageOutput)
            {
                captureSession.addOutput(stillImageOutput)
            }
        }
        catch
        {
            print("error: \(error.localizedDescription)")
        }
        guard let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) else
        {
            print("no preview layer")
            return
        }
        self.view.layer.addSublayer(previewLayer)
        previewLayer.frame = self.view.layer.frame
        captureSession.startRunning()
        self.view.addSubview(imageView)
    }

Upvotes: 0

Paulo
Paulo

Reputation: 14067

Based on the solution presented by mbuff24. Array methods include .first(where:) besides .filter()

guard let frontCamera = AVCaptureDevice.devices().first(where: { ($0 as AnyObject).position == .front }) as? AVCaptureDevice else {
            fatalError("No front facing camera found")
            }

Upvotes: 1

mbuff24
mbuff24

Reputation: 425

guard let device = AVCaptureDevice.devices().filter({ $0.position == .Front })
    .first as? AVCaptureDevice else {
        fatalError("No front facing camera found")
}

If you're looking for a shorter solution although .filter followed by .first isn't the most efficient

Upvotes: 9

Related Questions