Swift: запись отфильтрованного видео в реальном времени с фильтром | Конвертировать UIImage в CMSampleBuffer? - PullRequest
0 голосов
/ 12 марта 2020

Я использую 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)
            }
        }
    }

}
...