[Xcode/Swift] AVFoundation完全理解への道③ (AVCapture)

この記事で学ぶこと:

【録音・録画】AVCaptureの基本

①を読んでなくても問題ないですが、概念が曖昧というか方は①から読まれるのをおすすめします。👇

[Xcode/Swift] AVFoundation完全理解への道①

【録音・録画】AVCaptureの基本

1.1 カメラ & マイクへのアクセス方

まず最初の壁はPermission地獄
カメラ・マイクはセキュリティ的に必須で、Info.plistにキーを入れないと一切動かないので注意。

(Xcode26のBetaだと、GUIで操作できそうだった記憶)

<key>NSCameraUsageDescription</key>
<string>このアプリはカメラを使用します</string>
<key>NSMicrophoneUsageDescription</key>
<string>このアプリはマイクを使用します</string>

そしてアクセスリクエスト👇

import AVFoundation

AVCaptureDevice.requestAccess(for: .video) { granted in
    print("📸 Camera access:", granted)
}

AVCaptureDevice.requestAccess(for: .audio) { granted in
    print("🎙 Microphone access:", granted)
}

1.2 キャプチャセッションの構築手順

録音・録画は「入力 → セッション → 出力」の流れで進む。

AVCaptureSession
├─ Input(AVCaptureDeviceInput)
│   ├─ Camera (背面/前面)
│   └─ Microphone
└─ Output(AVCaptureOutput)
    ├─ AVCaptureMovieFileOutput(録画)
    ├─ AVCapturePhotoOutput(写真)
    └─ AVCaptureAudioDataOutput / VideoDataOutput(加工用)

最小コード例👇

let session = AVCaptureSession()

// 1. カメラデバイス取得
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera,
                                           for: .video, position: .back),
      let mic = AVCaptureDevice.default(for: .audio) else { return }

// 2. 入力追加
let cameraInput = try AVCaptureDeviceInput(device: camera)
let micInput = try AVCaptureDeviceInput(device: mic)

if session.canAddInput(cameraInput) { session.addInput(cameraInput) }
if session.canAddInput(micInput) { session.addInput(micInput) }

// 3. 出力追加(ここでは録画用)
let movieOutput = AVCaptureMovieFileOutput()
if session.canAddOutput(movieOutput) { session.addOutput(movieOutput) }

// 4. セッション開始
session.startRunning()

ポイント:

  • Input/Outputの追加はcanAddInput/canAddOutputでチェック必須
  • startRunning() は重い処理 → バックグラウンドQueueで呼ぶのがベター

1.3 プレビュー表示

録画アプリでは必須、ユーザーに「撮れてる映像」を見せる。
UIKitなら AVCaptureVideoPreviewLayer、SwiftUIなら UIViewRepresentable でラップする。

UIKit版:

let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.bounds
view.layer.addSublayer(previewLayer)

SwiftUI:

struct CameraPreview: UIViewRepresentable {
    let session: AVCaptureSession
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        let previewLayer = AVCaptureVideoPreviewLayer(session: session)
        previewLayer.videoGravity = .resizeAspectFill
        previewLayer.frame = UIScreen.main.bounds
        view.layer.addSublayer(previewLayer)
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {}
}

1.4 ファイル保存・写真撮影の流れ

動画録画:

AVCaptureMovieFileOutput を使って録画し、そのままファイル保存。

let output = AVCaptureMovieFileOutput()
session.addOutput(output)

let fileURL = URL(fileURLWithPath: NSTemporaryDirectory() + "test.mov")
output.startRecording(to: fileURL, recordingDelegate: self)

// 録画停止
output.stopRecording()

写真撮影: AVCapturePhotoOutput を使う。撮影はコマンド一発。

let photoOutput = AVCapturePhotoOutput()
session.addOutput(photoOutput)

let settings = AVCapturePhotoSettings()
photoOutput.capturePhoto(with: settings, delegate: self)

Delegateで画像データを受け取って保存すればOK。


次回: AVFoundationのよくある落とし穴

[Xcode/Swift] AVFoundation完全理解への道④ (落とし穴)