iOSカメラ表示ミニマムサンプル
はじめに
iOSでカメラの映像をViewに表示するにはAVFoundationを使用しますが、AVFoundationにはカメラ、音、入力出力の様々なメソッドやDelegateなどが紐づいているので、なかなかに複雑です。
カメラ表示をするだけのサンプルコードを見つけられず、複雑なコードを読むのがすごく辛かったのでカメラを表示するだけのシンプルなコードを解説します。
Swiftで書かれているサンプルも古いコードが多くそのままだと動かないものが多かったので誰かの助けになれば幸いです。
AVFoundation
AVCaptureSession()
AVCaptureSessionはデバイスの入出力を設定する根幹をになうクラスです。
今回は出来るだけシンプルにミニマムなコードで解説を行うため、出力の設定はなしです。
let captureSession = AVCaptureSession()
lazy var videoInput = { () -> AVCaptureDeviceInput in
//デフォルトだと背面のカメラが使用される
let videoDevice = AVCaptureDevice.default(for: .video)
return try! AVCaptureDeviceInput.init(device: videoDevice!)
}()
AVCaptureVideoPreviewLayer
AVCaptureVideoPreviewLayerはViewに対してカメラが映し出す映像を持っているので、映像を反映したいViewに貼り付けることでカメラのプレビューができるようになります。
private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
//モニターを可能にするlayer
return AVCaptureVideoPreviewLayer(session: self.captureSession)
}()
//反映したいViewに貼り付ける(サンプルではViewControllerのviewにくっつけています。)
セッションの開始
startRunningを呼び出すことでカメラの映像を映し出す処理が開始されます。重いので非同期で動かすのが良いらしいです。
DispatchQueue.global(qos: .userInitiated).async {
//こいつが開始されるとカメラの画像がViewに反映される
self.captureSession.startRunning()
}
Keyの登録
カメラを使用するのでUserからの許可が必要になります。許可がないとクラッシュするようなので実装必須です。
Property List Key
Privacy - Camera Usage Description
Source code
<dict>...
<key>NSCameraUsageDescription</key>
<string>ビデオ撮影のためにカメラを使用します。</string>
コード一覧
import UIKit
import AVFoundation
class ViewController: UIViewController {
//セッションのインスタンス
let captureSession = AVCaptureSession()
lazy var videoInput = { () -> AVCaptureDeviceInput in
//デフォルトだと背面のカメラが使用される
let videoDevice = AVCaptureDevice.default(for: .video)
return try! AVCaptureDeviceInput.init(device: videoDevice!)
}()
private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
//モニターを可能にするlayer
return AVCaptureVideoPreviewLayer(session: self.captureSession)
}()
override func viewDidLoad() {
super.viewDidLoad()
//背面カメラで入力することを紐づける
captureSession.addInput(videoInput)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
previewLayer.frame = self.view.bounds
previewLayer.videoGravity = .resizeAspectFill
self.view.layer.addSublayer(previewLayer)
//重いので非同期!
DispatchQueue.global(qos: .userInitiated).async {
//こいつが開始されるとカメラの画像がViewに反映される
self.captureSession.startRunning()
}
}
}
参考文献
[iOS] AVFundationを使用して、「ビデオ録画」や「連写カメラ」や「QRコードリーダー」や「バーコードリーダー」を作ってみた