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】バーコードリーダーをSwiftで作ってみた

[iOS] AVFundationを使用して、「ビデオ録画」や「連写カメラ」や「QRコードリーダー」や「バーコードリーダー」を作ってみた