AVFoundationを利用してカメラが取り込んだデータを表示する
ユースケース
iOSでは写真を撮影するためのフレームワークとしてiOSでは「UIImagePickerController」が用意されています。単純にカメラの機能を利用したいだけであればUIImagePickerControllerを利用するだけで充分です。しかし、UIImagePickerControllerではカメラに対するカスタマイズがあまり出来ません。カメラ機能に対して柔軟なカスタマイズを行いたいならAVFoundationフレームワークの使用を検討する必要があります。ただし、AVFoundationはUIImagePickerControllerと比較して非常に複雑な開発工程を踏む必要があります。
AVFoundationの構成
AVFoundationフレームワークは大きく2つに分かれます。ビデオまわりのAPIとオーディオに関係するAPIです。今回はビデオまわりのAPIのみを確認していきます。
AVFoundationを利用してカメラが写している風景を表示するために必要なクラス
AVFoundationを利用したカメラ映像の描画を行うためには以下に示す4つのクラスをうまく組み合わせて利用する必要があります。
上図はAV Foundationプログラミングより引用
AVCaptureSession
キャプチャセッションはデバイスの入力と出力の橋渡しを行うクラスです。入力されたデータをどこに出力するのかを管理してくれます。
AVCaptureDeviceInput
AVCaptureDeviceInputはカメラなどの物理デバイスのインターフェースを提供してくれるクラスです。
AVCaptureXXXOutput
キャプチャセッションからの出力をキャプチャするために利用するクラスです。
AVCapturePreviewLayer
カメラがキャプチャしているものを表示するためのクラスです。
サンプルコード
以上のクラスを組み合わせてカメラが取り込んだデータを表示するができます。以下のコードはこれらのクラスを組み合わせてカメラが写している映像を表示するためのサンプルコードです。
class ViewController: UIViewController { var previewLayer: AVCaptureVideoPreviewLayer? enum CameraError : Error { case noCamerasAvailable } func defaultDevice() throws -> AVCaptureDevice{ if let device = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .back) { return device } else if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back){ return device } else { throw CameraError.noCamerasAvailable } } override func viewDidLoad() { super.viewDidLoad() // 1. capture sessionの生成 let session:AVCaptureSession = AVCaptureSession() do{ // 2. カメラデバイスの取得 let cameraDevice:AVCaptureDevice = try defaultDevice() // 3. カメラデバイスからDeviceInputの作成 let cameraInput:AVCaptureDeviceInput = try AVCaptureDeviceInput(device:cameraDevice) // 4. セッションにDeviceInputを接続 if session.canAddInput(cameraInput){ session.addInput(cameraInput) } // 5. イメージをキャプチャするためのAVCaputureOutputを作成 let imageOutput:AVCapturePhotoOutput = AVCapturePhotoOutput() // 6. セッションにOutputを接続 if session.canAddOutput(imageOutput){ session.addOutput(imageOutput) } // 7. セッションを開始してデータ転送を開始する session.startRunning() }catch{ print(error) } //セッションに流れているデータを表示する //カメラデバイスから取り込んだデータを表示する時はAVCaptureVideoPreviewLayerを使用する self.previewLayer = AVCaptureVideoPreviewLayer(session: session) self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill self.previewLayer?.connection?.videoOrientation = .portrait self.previewLayer?.frame = view.frame self.view.layer.addSublayer(self.previewLayer!) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }