【问题标题】:Using AVCaptureVideoDataOutputSampleBufferDelegate without a preview window在没有预览窗口的情况下使用 AVCaptureVideoDataOutputSampleBufferDelegate
【发布时间】:2017-12-05 21:56:20
【问题描述】:

我正在开发一个基于 Swift 的 macOS 应用程序,我需要在其中捕获视频输入,但不将其显示在屏幕上...而不是显示视频,我想将缓冲的数据发送到其他地方进行处理,并且最终将其显示在SceneKit 场景中的对象上。

我有一个 CameraInput 类,它有一个 prepareCamera 方法:

    fileprivate func prepareCamera() {
        self.videoSession = AVCaptureSession()
        self.videoSession.sessionPreset = AVCaptureSession.Preset.photo

        if let devices = AVCaptureDevice.devices() as? [AVCaptureDevice] {
            for device in devices {
                if device.hasMediaType(AVMediaType.video) {
                    cameraDevice = device

                    if cameraDevice != nil  {
                        do {
                            let input = try AVCaptureDeviceInput(device: cameraDevice)


                            if videoSession.canAddInput(input) {
                                videoSession.addInput(input)
                            }


                           } catch {
                            print(error.localizedDescription)
                        }
                    }
                }
            }

            let videoOutput = AVCaptureVideoDataOutput()
            videoOutput.setSampleBufferDelegate(self as AVCaptureVideoDataOutputSampleBufferDelegate, queue: DispatchQueue(label: "sample buffer delegate", attributes: []))
            if videoSession.canAddOutput(videoOutput) {
                videoSession.addOutput(videoOutput)
            }
        }
    }

还有一个启动AVCaptureSession 会话的startSession 方法:

fileprivate func startSession() {
    if let videoSession = videoSession {
        if !videoSession.isRunning {
            self.videoInputRunning = true
            videoSession.startRunning()
        }
    }
}

我还实现了AVCaptureVideoDataOutputSampleBufferDelegate,我打算在其中捕获CMSampleBuffer 供以后使用:

extension CameraInput: AVCaptureVideoDataOutputSampleBufferDelegate {

    internal func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        print(Date())
    }
}

但是,委托永远不会被调用。这是我必须显示视频输出以便调用它的情况吗?

【问题讨论】:

  • 你在什么类下写这几行代码?你的输入设备是什么?
  • @ElTomato 输入设备只是我的 mac 的 iSIGht 相机。该类是一个名为 CameraInput 的自定义类,它继承自 NSObject。
  • 您没有使用 previewLayer。它是干什么用的?据我所知,你确实需要它。
  • @ElTomato 啊,是的;不小心留在了那里 - 我更新了上面的代码。

标签: swift macos avfoundation avcapturesession cmsamplebuffer


【解决方案1】:

您的问题与您是否(或不)显示捕获的视频的预览无关。

如果您使用的是 Swift 4(看起来确实如此),那么您要实现的委托方法签名不是 captureOutput(_:didOutputSampleBuffer:from:),而是 this

optional func captureOutput(_ output: AVCaptureOutput, 
              didOutput sampleBuffer: CMSampleBuffer, 
                     from connection: AVCaptureConnection)

无关提示:

  • 命名空间常量意味着如果你愿意,你可以更简洁;例如videoSession.sessionPreset = .photo

  • AVCaptureDevice.devices() 已弃用。而不是自己调用并循环设备,只需ask AVCaptureDevice for exactly the kind of device you want

    let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, 
                                           for: .video, position: .back)
    
  • 如果您的类已经声明符合AVCaptureVideoDataOutputSampleBufferDelegate 协议,则不需要在videoOutput.setSampleBufferDelegate(self as AVCaptureVideoDataOutputSampleBufferDelegate 中进行as 强制转换。


最后,如果您只是希望将来自摄像机的实时视频映射到 SceneKit 场景的某个部分,请注意,在 iOS 11 中,您可以将 AVCaptureDevice 分配给 SCNMaterialProperty 的 @987654334 @ 直接 - 无需自己抓取、处理和移动像素缓冲区。

【讨论】:

  • 很好的答案,这些提示很有用!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
相关资源
最近更新 更多