gpt4 book ai didi

swift - 使用 AVCaptureVideoDataOutput 正确录制视频

转载 作者:行者123 更新时间:2023-11-30 10:39:56 42 4
gpt4 key购买 nike

背景:

我使用 AVCaptureVideoDataOutputAVCaptureSession 和其他各种 AV 工具配合来创建视频 session ,以便我可以创建相机 session 。我可以实时了解相机在屏幕上看到的内容。

我使用 AVCaptureVideoDataOutput 而不是 AVCaptureMovieFileOutput ,因为我通过实时源获取的图像是使用 CIFilter 进行处理的。现在,我想记录按下按钮时向用户显示的内容。我对此的想法是使用下面的函数,因为我认为该函数捕获每一帧。我从 Apple's Page 中推断出这一点:

Delegates receive this message whenever the output captures and outputs a new video frame, decoding or re-encoding it as specified by its videoSettings property. Delegates can use the provided video frame in conjunction with other APIs for further processing.

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

我希望每个帧都在这里,这样我就可以使用 AVAssetWriter 并将缓冲区添加到 videoWriterInput 中。可以看到here,其中答案表明func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)方法每次都将sampleBuffer添加到videoWriterInput中。

我的努力:

我试图模拟上面的SO帖子,其中答案利用AVAssetWriterAVCaptureVideoDataOutput写入文件。但是,我的代码(如下所示)没有调用 AVCaptureVideoDataOutputSampleBufferDelegate func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) 委托(delegate)方法。

注意:这不是全部代码 - 我仅添加相关部分 - 如果缺少您需要的内容,请告诉我

VideoCapture.swift

class VideoCapture: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {

private let captureSession = AVCaptureSession()
private let videoDataOutput = AVCaptureVideoDataOutput()
private let dataOutputQueue = DispatchQueue(label: "com.Camera.dataOutputQueue")
private var videoConnection: AVCaptureConnection!

//NEVER GETS CALLED
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
print("Buf: \(sampleBuffer)")
}

func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
print("Drop Buff: \(sampleBuffer)")
}

init() {
//Some Setup
captureSession.sessionPreset = AVCaptureSession.Preset.high

//...
do {
// video output
videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
videoDataOutput.alwaysDiscardsLateVideoFrames = true
videoDataOutput.setSampleBufferDelegate(self, queue: dataOutputQueue)
guard captureSession.canAddOutput(videoDataOutput) else { fatalError() }
captureSession.addOutput(videoDataOutput)
videoConnection = videoDataOutput.connection(with: .video)
}
//...
}
}

AnotherFile.swift

class VC: UIViewController {

private var videoCapture: VideoCapture!

init() {
self.videoCapture = VideoCapture()
}

public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let videoCapture = videoCapture else {return}
videoCapture.startCapture()
}
}

我的期望:

我期待这个方法

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

被调用并至少打印出上面示例中的缓冲区。这没有发生,所以我无法进一步开发并将缓冲区插入 videoWriteInput 中进行记录。

实际发生的情况:

它从未被调用过。我确保使用 videoDataOutput.setSampleBufferDelegate(self, queue: dataOutputQueue) 设置委托(delegate),并清楚地表明委托(delegate)方法已创建。我确信使用自动完成功能,以便该方法是从 XCode 创建的,这样我就不会弄乱方法名称,例如 this SO post

问题:

我怎样才能正确地获取要调用的方法 - 假设我的直觉是正确的,该方法会为每个帧调用,并且是一个可以插入到我的 videoWriterInput 中的缓冲区 - 这样我就可以从 AVCaptureSession 录制视频我可以在屏幕上看到吗?

值得注意:

This 项目在调用方面起作用

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

this 确实有效。

编辑:

我发现由于某种原因,AVCaptureDataOutputSynchronizer 导致它无法调用委托(delegate)函数。有什么想法吗?

最佳答案

好吧,我已经找到我受折磨的理由了。所以,我使用 AVCaptureMetadataOutput , AVCaptureDepthDataOutput , AVCaptureAudioDataOutput ,和AVCaptureVideoDataOutput并使用 AVCaptureDataOutputSynchronizer 将它们组合起来。

因为我正在使用AVCaptureDataOutputSynchronizer ,它正在捕获此处的所有委托(delegate)调用。例如,我可以同步我的数据,它会调用 AVCaptureDataOutputSynchronizer委托(delegate)方法而不是其他单独的委托(delegate)。

dataOutputSynchronizer = AVCaptureDataOutputSynchronizer(dataOutputs: [videoDataOutput, depthDataOutput, metadataOutput])
dataOutputSynchronizer.setDelegate(self, queue: dataOutputQueue)

//... Some Code Later...

func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {

guard let syncedVideoData = synchronizedDataCollection.synchronizedData(for: videoDataOutput) as? AVCaptureSynchronizedSampleBufferData else { return }
guard !syncedVideoData.sampleBufferWasDropped else {
print("dropped video:\(syncedVideoData)")
return
}
let videoSampleBuffer = syncedVideoData.sampleBuffer
print(videoSampleBuffer)

let syncedDepthData = synchronizedDataCollection.synchronizedData(for: depthDataOutput) as? AVCaptureSynchronizedDepthData
var depthData = syncedDepthData?.depthData
if let syncedDepthData = syncedDepthData, syncedDepthData.depthDataWasDropped {
print("dropped depth:\(syncedDepthData)")
depthData = nil
}

// 顔のある位置のしきい値を求める
let syncedMetaData = synchronizedDataCollection.synchronizedData(for: metadataOutput) as? AVCaptureSynchronizedMetadataObjectData
var face: AVMetadataObject? = nil
if let firstFace = syncedMetaData?.metadataObjects.first {
face = videoDataOutput.transformedMetadataObject(for: firstFace, connection: videoConnection)
}
guard let imagePixelBuffer = CMSampleBufferGetImageBuffer(videoSampleBuffer) else { fatalError() }
}

这会按预期在每一帧被调用,我可以获得单独的数据集、音频、视频等,并用它们做我喜欢的事情。

关于swift - 使用 AVCaptureVideoDataOutput 正确录制视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57048430/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com