iOS アプリで動画撮影する際手ブレ補正を効かせる Swift コード

過去2回、AVFoundation を利用して動画を撮影する iOS アプリを実装するための Swift コードの断片を紹介した。

その中で調査したことで書いていなかったことがあったので、今回久々に紹介。Swift 4 以降で、iOS 13・14 の iPhone 11 Pro Max にて検証した。

今回紹介するのは、動画撮影時の「手ブレ補正」の指定を行う方法。AVCaptureVideoStabilizationMode という項目があるので、コレを指定してやると「映画レベルのビデオ手ブレ補正」を有効にできる。前回の記事で紹介したコード片のうち、動画を録画する処理の前段で指定してやる。

import UIKit
import AVFoundation
import Photos

class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {
  /// セッション
  var session: AVCaptureSession!
  /// ビデオデバイス
  var videoDevice: AVCaptureDevice!
  /// オーディオデバイス
  var audioDevice: AVCaptureDevice!
  /// ファイル出力
  var fileOutput: AVCaptureMovieFileOutput!
  
  // …… (中略) ……
  
  /// 録画を開始する : ボタンからこの関数を呼び出してあげる
  private func startRecording() {
    // Documents ディレクトリ直下にファイルを生成する
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    let documentsDirectory = paths[0] as String
    
    // 現在時刻をファイル名に付与することでファイル重複を防ぐ : "myvideo-20190101125900999.mp4" な形式になる
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyyMMddHHmmssSSS"
    let filePath: String? = "\(documentsDirectory)/myvideo-\(formatter.string(from: Date())).mp4"
    let fileURL = NSURL(fileURLWithPath: filePath!)
    
    // 今回追加したコード : 「ビデオ手ブレ補正」がサポートされているかどうか確認する
    if(fileOutput.connection(with: AVMediaType.video)?.isVideoStabilizationSupported)! {
      if #available(iOS 13.0, *) {
        // iOS v13 以降だと「cinematicExtended」というさらなる手ブレ補正モードが存在する
        fileOutput.connection(with: AVMediaType.video)?.preferredVideoStabilizationMode = AVCaptureVideoStabilizationMode.cinematicExtended
      } else {
        // そうでなければ「cinematic」モードを指定する
        fileOutput.connection(with: AVMediaType.video)?.preferredVideoStabilizationMode = AVCaptureVideoStabilizationMode.cinematic
      }
    }
    
    print("録画開始 : \(filePath!)")
    fileOutput?.startRecording(to: fileURL as URL, recordingDelegate: self)
    // XXX : あとココでプレビュー表示とか…
  }
}

isVideoStabilizationSupported で手ブレ補正がサポートされているか確認し、preferredVideoStabilizationMode にモードを指定してやる。通常手ブレ補正というと AVCaptureVideoStabilizationMode.cinematic を指定すれば良いが、iOS 13 以降・iPhone 11 Pro 辺りの機種からは、AVCaptureVideoStabilizationMode.cinematicExtended というさらに強力な手ブレ補正モードが選択できる。