观察者在AVFoundation captureOutput方法中导致滞后

时间:2018-09-06 22:13:20

标签: swift avfoundation avcapturesession

我有一个非常具体的问题,但希望有人可以帮助我。我正在使用AVFoundation创建具有实时预览的摄像机。我使用AVCaptureVideoDataOutput获取单个帧,并使用AVCaptureMetadataOutput检测面部。我还使用Dlib的面部界标预测器来显示用户脸上的界标点,并测量他们的眼睛之间的眼间距离。最后,我使用了AVAssetWriter,以便可以录制视频。

视图控制器上具有椭圆形状,因此用户知道将脸放在何处。当眼距在一定距离之间时,我希望椭圆变成蓝色,以便用户知道他们的脸在正确的位置。

目前,我已经通过从SessionHandler类向视图控制器发送通知来实现这一点。此方法有效,但是会导致视频中的每秒帧严重下降。我的速度是25fps(由我手动设置),现在是8-16。

还有没有其他方法可以通知视图控制器椭圆应该变为绿色?

这是发生问题的我的代码。我知道发生了很多事。

    // MARK: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioOutputSampleBufferDelegate
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

    if !currentMetadata.isEmpty {
        let boundsArray = currentMetadata
            .compactMap { $0 as? AVMetadataFaceObject }
            .map { (faceObject) -> NSValue in
                let convertedObject = output.transformedMetadataObject(for: faceObject, connection: connection)
                return NSValue(cgRect: convertedObject!.bounds)
        }

        if user.hasDlib {
            wrapper?.doWork(on: sampleBuffer, inRects: boundsArray)
            // Get the interocular distance so face is the correct place in the oval
            let interocularDistance = wrapper?.getEyeDistance()
            //print("Interocular Distance: \(interocularDistance)")

            if user.hasInterocularDistance {
                if interocularDistance! < 240 || interocularDistance! > 315 {
                    let name = Notification.Name(rawValue: setRemoveGreenEllipse)
                    NotificationCenter.default.post(name: name, object: nil)
                    //print("face not correct distance")
                    if videoRecorder.isRecording {
                        eyeDistanceCounter += 1
                        //print(eyeDistanceCounter)
                        if eyeDistanceCounter == 30 {
                            cancelledByUser = false
                            cancelledByEyeDistance = true
                            videoRecorder.cancel()
                            eyeDistanceCounter = 0
                        }
                    }
                } else {
                    //print("face correct distance")
                    eyeDistanceCounter = 0
                    let name = Notification.Name(rawValue: setGreenEllipse)
                    NotificationCenter.default.post(name: name, object: nil)
                }
            }

        }
    } else {

        // Check if face is detected during recording. If it isn't, then cancel recording
        if videoRecorder.isRecording {
            noFaceCount += 1
            if noFaceCount == 50 {
                cancelledByUser = false
                videoRecorder.cancel()
                noFaceCount = 0
            }
        }

    }

    if layer.status == .failed {
        layer.flush()
    }

    layer.enqueue(sampleBuffer)

    let writable = videoRecorder.canWrite()

    if writable {

        if videoRecorder.sessionAtSourceTime == nil {
            // Start Writing
            videoRecorder.sessionAtSourceTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
            videoRecorder.videoWriter.startSession(atSourceTime: videoRecorder.sessionAtSourceTime!)
            print("video session started")
        }

        if videoRecorder.videoWriterInput.isReadyForMoreMediaData {
            // write video buffer
            videoRecorder.videoWriterInput.append(sampleBuffer)
            //print("video buffering")
        }
    }
}

1 个答案:

答案 0 :(得分:0)

例如,您可能每30帧调用一次通知,而不是每帧调用一次。

如果在同一视图控制器中,则还可以直接调用颜色更改功能。如果没有,您可以定义一个委托方法并直接反对发送通知。