如何在 macOS 中使用 AVFoundation 采集视频数据?
How to use the AVFoundation to capture video data in macOS?
我根据网上找到的几个例子编写了下面的代码,目的是从 macOS 上的内置摄像头捕获视频数据。设置 AVCaptureSession
时未引发致命错误,但未调用委托,并且在我调用 captureSession.startRunning()
.
时立即记录了一些明显的错误
到目前为止,我已尝试对我的代码进行小幅调整(例如,删除输出中的 videoSettings
或会话中的 sessionPreset
),以及检查系统首选项我的测试应用程序具有相机访问权限。但是,日志仍然存在,并且没有调用委托。
CameraInput class(包括委托):
final class CameraInput: NSObject {
private lazy var sampleBufferDelegateQueue = DispatchQueue(label: "CameraInput")
private lazy var captureSession: AVCaptureSession = {
let session = AVCaptureSession()
session.sessionPreset = .hd1280x720
let device = AVCaptureDevice.default(for: .video)!
let input = try! AVCaptureDeviceInput(device: device)
session.addInput(input)
let output = AVCaptureVideoDataOutput()
output.videoSettings = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
kCVPixelBufferMetalCompatibilityKey as String: true
]
output.alwaysDiscardsLateVideoFrames = true
output.setSampleBufferDelegate(self, queue: self.sampleBufferDelegateQueue)
session.addOutput(output)
return session
}()
}
extension CameraInput: CVInput {
func start() {
guard !self.captureSession.isRunning else {
return
}
self.captureSession.startRunning()
}
func stop() {
guard self.captureSession.isRunning else {
return
}
self.captureSession.stopRunning()
}
}
extension CameraInput: AVCaptureVideoDataOutputSampleBufferDelegate {
private func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// Handle captured frame
}
}
ViewController(新 cocoa 应用程序中默认 viewcontroller):
class ViewController: NSViewController {
lazy var cameraInput = CameraInput()
override func viewDidLoad() {
super.viewDidLoad()
self.cameraInput.start()
}
}
记录的信息:
2019-01-02 16:27:15.821858+0100 TestApp[14182:1492243] [] CMIO_Unit_ScopeElement.h:200:SafeGetElement Throwing err: -67454
2019-01-02 16:27:15.823248+0100 TestApp[14182:1492243] [] CMIOUnitFigBaseObjectImpl.c:246:CMIOUnitCreateFromDescription Invalid paramater
2019-01-02 16:27:15.840190+0100 TestApp[14182:1492243] [] CMIO_Unit_Input_Device.cpp:244:GetPropertyInfo CMIOUInputFromProcs::GetPropertyInfo() failed for id 102, Error: -67456
非常感谢任何帮助使它工作的帮助!另外,如果需要更多信息,请通知我。
编辑
在 运行 进入 后,我已经排除了沙盒问题。
您的代码似乎没问题。尝试
- 在 Xcode
中创建一个新的 "CocoaApp/Swift" 项目
- 将您的两个代码片段粘贴到 AppDelegate
- 将
AVCaptureVideoDataOutputSampleBufferDelegate
添加到应用委托声明中
- 将
self.captureSession.startRunning()
添加到AppDelegateapplicationDidFinishLaunching
函数
- 在沙盒设置中启用相机使用
- 将
NSCameraUsageDescription
添加到 Info.plist(macOS 10.14 及更高版本)
我刚测试过,委托函数被重复调用。
我在 macOS 10.14 / XCode 10 上看到提到的日志输出(它没有显示在 macOS 10.13 / Xcode 9 上),但它不会阻止捕获。
所以问题不在问题中给出的代码中。确保所有对象都按预期实际创建,捕获会话设置运行,并且没有对象 - 特别是输出委托 - 过早释放。
您需要从您的 captureOutput:didOutput
方法中删除关键字 private
。
我猜它改变了签名足以让你的方法不被调用。
我 运行 进入这个确切的错误。标记的答案帮助我走上了正确的道路,但我觉得我的问题分歧很大,值得另一个答案
我的代码在不起作用时是这样的。
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!)
过去就是这样。我使用 Xcode 自动完成来获取当前版本。
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
这个故事的寓意... Conversion to Swift <insert version> is Available
并不总是完美的。
我根据网上找到的几个例子编写了下面的代码,目的是从 macOS 上的内置摄像头捕获视频数据。设置 AVCaptureSession
时未引发致命错误,但未调用委托,并且在我调用 captureSession.startRunning()
.
到目前为止,我已尝试对我的代码进行小幅调整(例如,删除输出中的 videoSettings
或会话中的 sessionPreset
),以及检查系统首选项我的测试应用程序具有相机访问权限。但是,日志仍然存在,并且没有调用委托。
CameraInput class(包括委托):
final class CameraInput: NSObject {
private lazy var sampleBufferDelegateQueue = DispatchQueue(label: "CameraInput")
private lazy var captureSession: AVCaptureSession = {
let session = AVCaptureSession()
session.sessionPreset = .hd1280x720
let device = AVCaptureDevice.default(for: .video)!
let input = try! AVCaptureDeviceInput(device: device)
session.addInput(input)
let output = AVCaptureVideoDataOutput()
output.videoSettings = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
kCVPixelBufferMetalCompatibilityKey as String: true
]
output.alwaysDiscardsLateVideoFrames = true
output.setSampleBufferDelegate(self, queue: self.sampleBufferDelegateQueue)
session.addOutput(output)
return session
}()
}
extension CameraInput: CVInput {
func start() {
guard !self.captureSession.isRunning else {
return
}
self.captureSession.startRunning()
}
func stop() {
guard self.captureSession.isRunning else {
return
}
self.captureSession.stopRunning()
}
}
extension CameraInput: AVCaptureVideoDataOutputSampleBufferDelegate {
private func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// Handle captured frame
}
}
ViewController(新 cocoa 应用程序中默认 viewcontroller):
class ViewController: NSViewController {
lazy var cameraInput = CameraInput()
override func viewDidLoad() {
super.viewDidLoad()
self.cameraInput.start()
}
}
记录的信息:
2019-01-02 16:27:15.821858+0100 TestApp[14182:1492243] [] CMIO_Unit_ScopeElement.h:200:SafeGetElement Throwing err: -67454
2019-01-02 16:27:15.823248+0100 TestApp[14182:1492243] [] CMIOUnitFigBaseObjectImpl.c:246:CMIOUnitCreateFromDescription Invalid paramater
2019-01-02 16:27:15.840190+0100 TestApp[14182:1492243] [] CMIO_Unit_Input_Device.cpp:244:GetPropertyInfo CMIOUInputFromProcs::GetPropertyInfo() failed for id 102, Error: -67456
非常感谢任何帮助使它工作的帮助!另外,如果需要更多信息,请通知我。
编辑
在 运行 进入
您的代码似乎没问题。尝试
- 在 Xcode 中创建一个新的 "CocoaApp/Swift" 项目
- 将您的两个代码片段粘贴到 AppDelegate
- 将
AVCaptureVideoDataOutputSampleBufferDelegate
添加到应用委托声明中 - 将
self.captureSession.startRunning()
添加到AppDelegateapplicationDidFinishLaunching
函数 - 在沙盒设置中启用相机使用
- 将
NSCameraUsageDescription
添加到 Info.plist(macOS 10.14 及更高版本)
我刚测试过,委托函数被重复调用。 我在 macOS 10.14 / XCode 10 上看到提到的日志输出(它没有显示在 macOS 10.13 / Xcode 9 上),但它不会阻止捕获。
所以问题不在问题中给出的代码中。确保所有对象都按预期实际创建,捕获会话设置运行,并且没有对象 - 特别是输出委托 - 过早释放。
您需要从您的 captureOutput:didOutput
方法中删除关键字 private
。
我猜它改变了签名足以让你的方法不被调用。
我 运行 进入这个确切的错误。标记的答案帮助我走上了正确的道路,但我觉得我的问题分歧很大,值得另一个答案
我的代码在不起作用时是这样的。
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!)
过去就是这样。我使用 Xcode 自动完成来获取当前版本。
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
这个故事的寓意... Conversion to Swift <insert version> is Available
并不总是完美的。