Я использую AVCaptureSession с AVCaptureOutput для отображения видео в реальном времени (AVCaptureVideoDataOutput) и аудио (AVCaptureAudioDataOutput) на экране. Так как captureOutput вызывается для видеовыхода, я применяю фильтр к CMSampleBuffer, преобразовываю его в UIImage и показываю его на экране через UIView. UIView успешно показывает отфильтрованный видеопоток.
Однако теперь я хочу ЗАПИСАТЬ ФИЛЬТРИРОВАННОЕ видео. Для записи видео я создал AVAssetWriter с videoWriterInput (AVAssetWriterInput). ПРОБЛЕМА: AVAssetWriterInput принимает CMSampleBuffer, а CMSampleBuffer из исходного captureOutput НЕ фильтруется.
- Могу ли я применить фильтр к CMSampleBuffer?
- Можно ли преобразовать FilterImage (UIImage) обратно? в CMSampleBuffer?
Спасибо, вперед!
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
print("Capturing output.")
//video
if output as? AVCaptureVideoDataOutput != nil && connection.isVideoOrientationSupported {
//set up video camera
connection.videoOrientation = .portrait
connection.preferredVideoStabilizationMode = .off
if self.videoDeviceInput.device.position == .front {
connection.isVideoMirrored = true
} else {
connection.isVideoMirrored = false
}
//add filter
let filter = CIFilter(name: "CIComicEffect")!
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let cameraImage = CIImage(cvPixelBuffer: pixelBuffer)
//display image on screen
if self.isFiltered {
filter.setValue(cameraImage, forKey: kCIInputImageKey) //filter image
let image = UIImage(ciImage: (filter.value(forKey: kCIOutputImageKey) as! CIImage))
DispatchQueue.main.async {
self.videoImageView.image = image
}
} else {
let image = UIImage(ciImage: cameraImage)
DispatchQueue.main.async {
self.videoImageView.image = image
}
}
if isRecording {
print("Is recording video.")
//if videoWriterInput is ready to record video and audio
if videoWriterInput.isReadyForMoreMediaData && audioWriterInput.isReadyForMoreMediaData {
//if first time recording video in writer, add beginning time to videoWRiter
if sessionAtSourceTime == nil {
//Start writing
sessionAtSourceTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
videoWriter.startSession(atSourceTime: sessionAtSourceTime!)
}
//write video
videoWriterInput.append(sampleBuffer)
}
}
}
//audio
if (output as? AVCaptureAudioDataOutput) != nil {
if isRecording {
print("Is recording audio.")
//if videoWriterInput is ready to record video and audio
if videoWriterInput.isReadyForMoreMediaData && audioWriterInput.isReadyForMoreMediaData {
//Write audio
audioWriterInput.append(sampleBuffer)
}
}
}
}