使用Front Camera for AVCaptureDevice预览图层自动像Snapchat或Houseparty(Swift 3)

时间:2016-12-21 06:36:08

标签: swift swift3 avfoundation xcode8 avcapturesession

基本上我要做的就是让AVCaptureDevice的前置摄像头成为AVCaptureSession期间应用程序的第一个也是唯一的选择。

我查看了StackOverflow,从iOS 10,Swift 3和Xcode 8开始,所有提供的方法和答案都已弃用。

我知道您应该使用AVCaptureDeviceDiscoverySession枚举设备并查看它们以区分正面和背面,但我不确定如何这样做。

有人可以帮忙吗?如果是这样的话会很棒!

这是我的代码:

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    previewLayer.frame = singleViewCameraSlot.bounds
    self.singleViewCameraSlot.layer.addSublayer(previewLayer)
    captureSession.startRunning()

}



lazy var captureSession: AVCaptureSession = {
    let capture = AVCaptureSession()
    capture.sessionPreset = AVCaptureSessionPreset1920x1080
    return capture
}()

lazy var previewLayer: AVCaptureVideoPreviewLayer = {
    let preview =  AVCaptureVideoPreviewLayer(session: self.captureSession)

    preview?.videoGravity = AVLayerVideoGravityResizeAspect
    preview?.connection.videoOrientation = AVCaptureVideoOrientation.portrait
    preview?.bounds = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
    preview?.position = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)

    return preview!
}()


func setupCameraSession() {


    let frontCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) as AVCaptureDevice

    do {
        let deviceInput = try AVCaptureDeviceInput(device: frontCamera)

        captureSession.beginConfiguration()

        if (captureSession.canAddInput(deviceInput) == true) {
            captureSession.addInput(deviceInput)
        }

        let dataOutput = AVCaptureVideoDataOutput()

        dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) : NSNumber(value: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange as UInt32)]
        dataOutput.alwaysDiscardsLateVideoFrames = true

        if (captureSession.canAddOutput(dataOutput) == true) {
            captureSession.addOutput(dataOutput)
        }

        captureSession.commitConfiguration()

        let queue = DispatchQueue(label: "io.goodnight.videoQueue")
        dataOutput.setSampleBufferDelegate(self, queue: queue)

    }
    catch let error as NSError {
        NSLog("\(error), \(error.localizedDescription)")
    }

}

2 个答案:

答案 0 :(得分:2)

如果您只需要根据简单的特征找到单个设备(例如可以拍摄视频的前置摄像头),只需使用AVCaptureDevicedefaultDevice(withDeviceType:mediaType:position:)。例如:

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

对于大多数用例来说,确实是这样。

还有AVCaptureDeviceDiscoverySession作为迭代devices数组的旧方法的替代品。但是,您可以使用新的defaultDevice(withDeviceType:mediaType:position:)方法找到您通常遍历devices数组的大部分内容,因此您可以使用它并编写更少的代码。

AVCaptureDeviceDiscoverySession值得使用的情况是不太常见,更复杂的情况:假设您想要找到支持特定帧速率的所有设备,或者使用键值观察来查看何时设置可用的设备更改。

顺便说一句......

  

我已经浏览了StackOverflow,从iOS 10,Swift 3和Xcode 8开始,所有提供的方法和答案都已弃用。

如果您阅读Apple的这些方法的文档(至少this onethis onethis one),您会看到一些弃用警告建议使用什么代替。还有a guide到iOS 10 / Swift 3照片捕获系统,还有一些sample code都显示了这些API的当前最佳做法。

答案 1 :(得分:0)

如果您明确需要前置摄像头,可以使用此处指定的AVCaptureDeviceDiscoverySession。

https://developer.apple.com/reference/avfoundation/avcapturedevicediscoverysession/2361539-init

这允许您指定要搜索的设备类型。以下(未经测试)应该为您提供前置摄像头。

let deviceSessions = AVCaptureDeviceDiscoverySession(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.front)

此deviceSessions具有devices属性,该属性是AVCaptureDevice类型的数组,仅包含与该搜索条件匹配的设备。

deviceSessions?.devices

这应该是0或1,具体取决于设备是否具有前置摄像头(例如某些iPod不会)。