Я пытаюсь использовать AVCaptureDataOutputSynchronizer для захвата мультимедиа с нескольких выходов захвата.У меня проблемы с захватом аудиоданных в dataOutputSynchronizer, так как audioData
в выражении guard всегда дает сбой.У меня нет проблем с захватом videoData
, и я могу отобразить кадр с помощью приведенного ниже кода.
Интересно, если это проблема с AVCaptureSynchronizedSampleBufferData, но AVCaptureSynchronizedSampleBufferData является контейнером для собранных видео или аудио сэмпловиспользуя синхронизированный захват.
Я не уверен, что проблема в том, что я неправильно настраиваю AVCaptureAudioDataOutput.Вот мой класс ViewController, инициализирующий и извлекающий видео и аудио данные.
Обратите внимание, что я запускаю это на iPhoneXS и работаю с iOS 12. Код написан быстро.Любая помощь с попыткой отладки это было бы здорово!
//
// ViewController.swift
// AudioVideoSyncTest
//
// Created by Andrew Mendez on 2/23/19.
// Copyright © 2019 Andrew Mendez. All rights reserved.
//
import UIKit
import AVFoundation
class ViewController: UIViewController,AVCaptureDataOutputSynchronizerDelegate,AVCaptureVideoDataOutputSampleBufferDelegate,AVCaptureAudioDataOutputSampleBufferDelegate {
var capSession:AVCaptureSession!
var videoDataOutput = AVCaptureVideoDataOutput()
var audioDataOutput = AVCaptureAudioDataOutput()
var dataOutputSynchronizer:AVCaptureDataOutputSynchronizer!
var dataOutputQueue = DispatchQueue(label: "com.amendez.dataOutputQueue")
@IBOutlet var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initSession()
capSession.startRunning()
}
func initSession(){
capSession = AVCaptureSession()
capSession.sessionPreset = .photo
let dualCameraDevice = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .unspecified)
let audioDevice = AVCaptureDevice.default(for: .audio)
let videoInput = try? AVCaptureDeviceInput(device: dualCameraDevice!)
let audioInput = try? AVCaptureDeviceInput(device: audioDevice!)
do{
if capSession.canAddInput(videoInput!) == true{
capSession.addInput(videoInput!)
}else{print("Issue input camera")}
if capSession.canAddInput(audioInput!) == true {
capSession.addInput(audioInput!)
} else {print("Issue Adding audio input")}
// configuring outputs
// video output
videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
videoDataOutput.alwaysDiscardsLateVideoFrames = true
videoDataOutput.setSampleBufferDelegate(self, queue: dataOutputQueue)
guard capSession.canAddOutput(videoDataOutput) else { fatalError() }
capSession.addOutput(videoDataOutput)
let videoConnection = videoDataOutput.connection(with: .video)
videoConnection!.videoOrientation = .portrait
// audio
guard capSession.canAddOutput(audioDataOutput) else {
print("FAILED");fatalError()}
audioDataOutput.setSampleBufferDelegate(self , queue: dataOutputQueue)
capSession.addOutput(audioDataOutput)
// synchronizer
dataOutputSynchronizer = AVCaptureDataOutputSynchronizer(dataOutputs: [
videoDataOutput,
audioDataOutput])
dataOutputSynchronizer.setDelegate(self, queue: dataOutputQueue)
}catch{
print("Error Config Input")
}
}
@IBAction func startRecord(_ sender: Any) {
}
@IBAction func stopRecord(_ sender: Any) {
}
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
//get video data
guard let videoData = synchronizedDataCollection.synchronizedData(for: videoDataOutput) as? AVCaptureSynchronizedSampleBufferData else{
return
}
guard !videoData.sampleBufferWasDropped else{
print("Dropped video:\(videoData)")
return
}
let pixBuffer = CMSampleBufferGetImageBuffer(videoData.sampleBuffer)
DispatchQueue.main.async {
self.imageView.image = UIImage(ciImage: CIImage(cvImageBuffer:pixBuffer! ))
}
//get video data
guard let audioData = synchronizedDataCollection.synchronizedData(for: audioDataOutput) as? AVCaptureSynchronizedSampleBufferData else{
print("Error getting Audio Buffer")
return
}
guard !audioData.sampleBufferWasDropped else{
print("Dropped audio:\(audioData)")
return
}
print(audioData.sampleBuffer)
}
}