web-dev-qa-db-fra.com

Comment obtenir la caméra avant, la caméra arrière et le son avec AVCaptureDeviceDiscoverySession

Avant la sortie de iOS 10, j'utilisais le code suivant pour obtenir la capture vidéo et audio de mon enregistreur vidéo:

 for device in AVCaptureDevice.devices()
 {
     if (device as AnyObject).hasMediaType( AVMediaTypeAudio )
     {
         self.audioCapture = device as? AVCaptureDevice
     }
     else if (device as AnyObject).hasMediaType( AVMediaTypeVideo )
     {
         if (device as AnyObject).position == AVCaptureDevicePosition.back
         {
             self.backCameraVideoCapture = device as? AVCaptureDevice
         }
         else
         {
             self.frontCameraVideoCapture = device as? AVCaptureDevice
         }
     }
 }

Lorsque iOS 10 est enfin sorti, j'ai reçu l'avertissement suivant lorsque j'exécutais mon code. Notez que mon enregistreur vidéo fonctionnait toujours sans à-coups pendant environ deux semaines.

'devices ()' est obsolète dans iOS 10.0: utilisez plutôt AVCaptureDeviceDiscoverySession.

Alors que je courais mon code ce matin, mon enregistreur vidéo a cessé de fonctionner. xCode8 ne me donne pas d'erreurs mais la previewLayer pour la capture de la caméra est complètement blanche. Lorsque je commence à enregistrer, le message d'erreur suivant s'affiche:

Error Domain = AVFoundationErrorDomain Code = -11800 "L'opération n'a pas pu être complétée" UserInfo = {NSLocalizedDescription = L'opération n'a pas pu être terminée, NSUnderlyingError = 0x17554440 {Domaine d'erreur = NSOSStatusErrorDomain Code = -12780 "(null)"}, NSLocalizedReprotection erreur inconnue survenue (-12780)}

Je pense que cela a quelque chose à voir avec le fait que j'utilise l'approche obsolète AVCaptureDevice.devices(). Par conséquent, je me demandais comment utiliser AVCaptureDeviceDiscoverySession à la place?

Merci d'avance pour votre aide!

33
AndreasLukas

Vous pouvez obtenir la caméra frontale avec les éléments suivants:

AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .front)

La caméra de recul:

AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)

Et le micro:

AVCaptureDevice.default(.builtInMicrophone, for: AVMediaType.audio, position: .unspecified)
67
born_stubborn

Swift 4, iOS 10+ et Xcode 10.1 remplace

if let cameraID = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)?.localizedName {
       //cameraID = "Front Camera"
}

avec AVCaptureDevice.DiscoverySession implementation

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

Besoin de l'envelopper avec #available (iOS 10, *) check.

11

Voici mon code (Swift 3) pour obtenir la position de la caméra:

// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(_ position: AVCaptureDevicePosition) -> AVCaptureDevice?
{
    if let deviceDescoverySession = AVCaptureDeviceDiscoverySession.init(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera],
                                                          mediaType: AVMediaTypeVideo,
                                                          position: AVCaptureDevicePosition.unspecified) {

        for device in deviceDescoverySession.devices {
            if device.position == position {
                return device
            }
        }
    }

    return nil
}

Si vous le souhaitez, vous pouvez également obtenir les nouveaux types devicesTypes de l'iPhone 7+ (double caméra) en modifiant le tableau deviceTypes. 

Voici une bonne lecture: https://forums.developer.Apple.com/thread/63347

11
hefgi

Cela fonctionne sur Xcode 9.2 et Swift 4

AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)

https://developer.Apple.com/documentation/avfoundation/avcapturedevice/2361508- par défaut

7
atereshkov

Swift 3

Pour sélectionner la caméra de recul: (vous pouvez aussi changer .back au besoin)

Pour sélectionner un autre deviceType simple, ajoutez-le à l'intérieur du [] (c'est-à-dire: 

[deviceTypeCamera, AVCaptureDeviceType.builtInMicrophone] 

(ou créer un let privé ... comme je l'ai fait dans le code avec la caméra de recul)

 private let position = AVCaptureDevicePosition.back
 private let deviceTypeBackCamera = AVCaptureDeviceType.builtInWideAngleCamera

 private func selectCaptureDevice() -> AVCaptureDevice? {
    return AVCaptureDeviceDiscoverySession(deviceTypes: [deviceTypeBackCamera], mediaType: AVMediaTypeVideo, position: position).devices.first

 }
3
MLBDG

exemple: iOS 11 Swift 4

override func viewDidLoad() {
    super.viewDidLoad()

    // Get the back-facing camera for capturing videos

    // AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
    let deviceDiscoverySession = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)

   guard let captureDevice = deviceDiscoverySession else {
       print("Failed to get the camera device")
       return
   }

    do {
        // Get an instance of the AVCaptureDeviceInput class using the previous device object.
        let input = try AVCaptureDeviceInput(device: captureDevice)

        // Set the input device on the capture session.
        captureSession.addInput(input)

    } catch {
        // If any error occurs, simply print it out and don't continue any more.
        print(error)
        return
    }

    // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
    videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
    videoPreviewLayer?.frame = view.layer.bounds
    view.layer.addSublayer(videoPreviewLayer!)

    // Start video capture.
    captureSession.startRunning()
2
Harry McGovern

Essayez le code ci-dessous pour obtenir l'identifiant de la caméra:

NSString *cameraID = nil;

NSArray *captureDeviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera];
AVCaptureDeviceDiscoverySession *captureDevice = 
              [AVCaptureDeviceDiscoverySession 
                discoverySessionWithDeviceTypes:captureDeviceType 
                mediaType:AVMediaTypeVideo 
                position:AVCaptureDevicePositionUnspecified];

cameraID = [captureDevice.devices.lastObject localizedName];
2
yoell32

Pour mon application de capture vidéo, j'utilise le code suivant pour obtenir le micro, les caméras avant et arrière et j'ai testé ce code de iOS 7 à 10.0.2.

        var frontCamera : AVCaptureDevice?
        var rearCamera : AVCaptureDevice?

        captureSession = AVCaptureSession()

        let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)

        let audioDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeAudio)

        for mic in audioDevices {
            audioDevice = mic as? AVCaptureDevice
            audioCapturePossible = true
        }

        for device in devices {
            if device.position == AVCaptureDevicePosition.Front {
                frontCamera = device as? AVCaptureDevice
                hasFrontCamera = true
            }
            else if device.position == AVCaptureDevicePosition.Back {
                rearCamera = device as? AVCaptureDevice
                hasRearCamera = true
            }

        }
1
Hammadzafar

Swift 4 (xCode 10.1)

C'est ce qui a fonctionné pour moi dans la dernière version de Swift. Je n’ai pas vu cette réponse, et il m’a fallu un certain temps pour comprendre, voici comment obtenir la caméra frontale.

 if let device = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera , mediaType: AVMediaTypeVideo, position: .front)  {
    //Do the camera thing here..
}
0
Dave Levy