简体   繁体   English

如何使用 AVCaptureDeviceDiscoverySession 获取前置摄像头、后置摄像头和音频

[英]How to get front camera, back camera and audio with AVCaptureDeviceDiscoverySession

Before iOS 10 came out I was using the following code to get the video and audio capture for my video recorder:在 iOS 10 出现之前,我使用以下代码来获取我的录像机的视频和音频捕获:

 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
         }
     }
 }

When iOS 10 finally came out, I received the following warning when I was running my code.当 iOS 10 终于出来时,我在运行我的代码时收到以下警告。 Note that my video recorder was still working smoothly for about 2 weeks.请注意,我的录像机在大约 2 周内仍能正常工作。

'devices()' was deprecated in iOS 10.0: Use AVCaptureDeviceDiscoverySession instead. 'devices()' 在 iOS 10.0 中被弃用:改用 AVCaptureDeviceDiscoverySession。

As I was running my code this morning, my video recorder stopped working.当我今天早上运行我的代码时,我的录像机停止工作。 xCode8 does not give me any errors but the previewLayer for the camera capture is completely white. xCode8 没有给我任何错误,但相机捕获的 previewLayer 是完全白色的。 When I then start recording I receive the following error:当我开始录制时,我收到以下错误:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x17554440 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12780)} Error Domain=AVFoundationErrorDomain Code=-11800 "操作无法完成" UserInfo={NSLocalizedDescription=操作无法完成,NSUnderlyingError=0x17554440 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"},NSLocalizedFailureReason=An发生未知错误 (-12780)}

I believe that has something to do with the fact that I am using the deprecated approach AVCaptureDevice.devices() .我相信这与我使用不推荐使用的方法AVCaptureDevice.devices()的事实有关。 Hence, I was wondering how to use AVCaptureDeviceDiscoverySession instead?因此,我想知道如何使用AVCaptureDeviceDiscoverySession代替?

Thank you for your help in advance!提前感谢您的帮助!

You can get the front camera with the following:您可以通过以下方式获得前置摄像头:

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

The back camera:后置摄像头:

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

And the microphone:还有麦克风:

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

Here's my code (Swift 3) to get camera position :这是我获取相机位置的代码(Swift 3):

// 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
}

If you want, you can also get the new devicesTypes from iPhone 7+ (dual camera) by changing the deviceTypes array.如果需要,您还可以通过更改 deviceTypes 数组从 iPhone 7+(双摄像头)获取新的 devicesTypes。

Here's a good read : https://forums.developer.apple.com/thread/63347这是一个很好的阅读: https : //forums.developer.apple.com/thread/63347

Swift 4, iOS 10+ and Xcode 10.1 replaces Swift 4、iOS 10+ 和Xcode 10.1取代

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

with AVCaptureDevice.DiscoverySession implementation使用AVCaptureDevice.DiscoverySession实现

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

Need to wrap it with #available(iOS 10,*) check.需要用#available(iOS 10,*)检查包装它。

It works on Xcode 9.2 and Swift 4它适用于Xcode 9.2 和 Swift 4

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

https://developer.apple.com/documentation/avfoundation/avcapturedevice/2361508-default https://developer.apple.com/documentation/avfoundation/avcapturedevice/2361508-default

Swift 3斯威夫特 3

For selecting the back camera:(also you can change .back as needed)用于选择后置摄像头:(您也可以根据需要更改 .back)

For selecting another deviceType simple add it inside the [ ] (ie:要选择另一个 deviceType,只需将其添加到 [] 中(即:

[deviceTypeCamera, AVCaptureDeviceType.builtInMicrophone] [deviceTypeCamera, AVCaptureDeviceType.builtInMicrophone]

(or create a private let... like I did in the code with the back camera) (或创建一个私人让......就像我在带有后置摄像头的代码中所做的那样)

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

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

 }

example: iOS 11 Swift 4示例: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()

Try below code to get camera ID:尝试以下代码以获取相机 ID:

NSString *cameraID = nil;

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

cameraID = [captureDevice.devices.lastObject localizedName];

For my video capture app I'm using the following code to get the mic, front and rear camera and I've tested this code from iOS 7 to 10.0.2.对于我的视频捕获应用程序,我使用以下代码来获取麦克风、前后摄像头,并且我已经测试了从 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
            }

        }

Swift 4 (xCode 10.1)斯威夫特 4 (xCode 10.1)

This is what worked for me in the latest version of Swift.这在最新版本的 Swift 中对我有用。 I did not see this answer, and it took me a while to suss out so here is how to get the front facing camera.我没有看到这个答案,我花了一段时间才弄清楚,所以这里是如何获得前置摄像头。

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

Simplified:简化:

func getCamera(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
    let deviceDescoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera], mediaType: .video, position: .unspecified)
    return deviceDescoverySession.devices.first(where: { $0.position == position })
}

// and you can use like that:

guard let device = getCamera(with: .back) else { return }

在 Swift 5 中更容易

AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front)

05/2019 : 05/2019 :

 //video
        self.session = AVCaptureSession()
        guard
            let videoDeviceInput = try? AVCaptureDeviceInput(device: device!),
            self.session!.canAddInput(videoDeviceInput)
            else { return }
        self.session!.addInput(videoDeviceInput)

  //audio
        guard
            let audioDeviceInput = try? AVCaptureDeviceInput(device: mic!),
            self.session!.canAddInput(audioDeviceInput)
            else { return }
        self.session!.addInput(audioDeviceInput) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM