Dans l’article précédent, nous avons vu comment utiliser AVCaptureSession
et AVCapturePhotoOutput
pour prendre une photo.
Voyons comment utiliser la classe AVCaptureVideoOutput
. Alors que AVCapturePhotoOutput
offre une fonction capturePhoto
, dans le cas de AVCaptureVideoOutput
, le delegate permet d’accéder à un buffer avec la fonction captureOutput(_ output: AVCaptureOutput, didOutput...)
qui est appelée à chaque fois qu’une nouvelle image est disponible.
Préparer la Capture Session
La captureSession est paramétrée de la même manière que dans le projet précédent, mais à la place de AVCapturePhotoOutput
, nous créons un AVCaptureVideoOutput
:
let videoOutput = AVCaptureVideoDataOutput() videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue")) captureSession.addOutput(videoOutput)
Avec l’affectation du delegate, nous devons créer une DispatchQueue. La capture vidéo s’effectue toujours sur un thread séparé. Dans les fonctions du delegate, nous ne sommes donc pas dans le main thread.
Récupérer une image du flux vidéo
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } let ciImage = CIImage(cvImageBuffer: imageBuffer).oriented(.right) // maj captureView dans le main thread DispatchQueue.main.async { self.captureView.image = UIImage(ciImage: ciImage) } }
Le buffer nous renvoie un objet CVImageBuffer qui peut être converti en CIImage, le format image de Core Image, qui à son tour peut être traduit en UIImage pour l’affichage. L’affectation d’une image à une view doit toujours se fait dans le main thread.
Pourquoi faire une capture d’image via un flux vidéo ? Pour faire de la reconnaissance d’image en temps réel, ce que je détaillerai dans un prochain article.
Le code source de cet article est disponible ici.