🎬

【iOS】AVFoundationを使用してLive Photos撮影アプリを開発する

2021/12/07に公開


AVFoundationを使用してLive Photos撮影アプリを開発する方法について書きます。前々回の記事で開発した写真撮影機能アプリに対して、Live Photos撮影機能を追加する形で解説していきます。iPhoneのカメラを立ち上げて画面にカメラの映像を表示するまでの処理は上記記事で解説していますので必要に応じてご参照ください。本記事のサンプルコードは以下に置いています。
https://github.com/NAOYA-MAEDA-DEV/AVFoundation-Camera-App

Live Photosキャプチャを有効にする

photoOutput がLive Photosキャプチャをサポートしているかを確認した後に、Live Photosキャプチャを有効にしておきます。

Live Photos撮影の開始

AVCapturePhotoOutputcapturePhoto を実行することでLive Photos撮影が開始します。capturePhoto の引数に、Live Photos撮影開始から完了するまでにコールされるデリゲートメソッドの委譲先と、撮影する写真のオプション情報を格納したAVCapturePhotoSettingsオブジェクトを指定します。移譲先はself つまり以下のコードを記述したViewController を指定しています。
前々回の記事で写真を撮影して保存するだけならAVCapturePhotoSettings に変更を加える必要がないと説明しましたが、Live Photos撮影を行う時には少し変更が必要です。
Live Photosは静止画とショートムービーの両方をキャプチャし、一つのアセットとしてフォトライブラリに保存します。AVCapturePhotoSettings オブジェクトには生成されるショートムービーを一時的に保存するURLを指定します。

Live Photos撮影で使用するデリゲートメソッド

Live Photos撮影開始から終了までの間にいくつかのデリゲートメソッドがコールされますが、使用するデリゲートメソッドは以下の5つです。

  • func photoOutput(AVCapturePhotoOutput, willBeginCaptureFor: AVCaptureResolvedPhotoSettings)
  • func photoOutput(AVCapturePhotoOutput, didFinishProcessingPhoto: AVCapturePhoto, error: Error?)
  • func photoOutput(AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt: URL, resolvedSettings: AVCaptureResolvedPhotoSettings)
  • func photoOutput(AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt: URL, duration: CMTime, photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?)
  • func photoOutput(AVCapturePhotoOutput, didFinishCaptureFor: AVCaptureResolvedPhotoSettings, error: Error?)

上記デリゲートメソッドを前項でデリゲートの移譲先に指定したViewController に記述します。

Live Photos撮影のハンドリング処理

撮影開始

Live Photosの撮影が開始するタイミングでfunc photoOutput(AVCapturePhotoOutput, willBeginCaptureFor: AVCaptureResolvedPhotoSettings) がコールされます。iOSの標準カメラではこのタイミングで画面中央上側に「Live」を表示しています。

写真の出力完了

写真の出力が完了したタイミングでfunc photoOutput(AVCapturePhotoOutput, didFinishProcessingPhoto: AVCapturePhoto, error: Error?) がコールされます。引数のphotoが写真データになります。photoの型はAVCapturePhoto で、このままではフォトライブラリに保存することができません。そこでfileDataRepresentation() を使用することでフォトライブラリに保存することができるData?型に変換しています。Live Photosを保存する時にこのData? 型のオブジェクトが必要になりますので、変数で保持しておきます。

ショートムービーの撮影終了

ショートムービーの撮影が終了したタイミングでphotoOutput(AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt: URL, resolvedSettings: AVCaptureResolvedPhotoSettings) がコールされます。iOSの標準カメラではこのタイミングで画面中央上側に表示していた「Live」を非表示にしています。

ショートムービーの出力完了

ショートムービーの出力が完了したタイミングでphotoOutput(AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt: URL, duration: CMTime, photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) がコールされます。引数のoutputFileURL は撮影したショートムービーが保存されているパスです。Live Photosを保存する時にこのURLが必要になりますので、変数で保持しておきます。

Live Photosの保存

撮影に必要な一連の処理が全て完了したタイミングでfunc photoOutput(AVCapturePhotoOutput, didFinishCaptureFor: AVCaptureResolvedPhotoSettings, error: Error?) がコールされます。このデリゲートメソッド内でPHPhotoLibrary.shared().performChanges を使用してフォトライブラリにLivePhotosを保存しています。creationRequest.addResource で撮影した写真とショートムービーを指定して保存してLive Photosの保存が完了です。

Discussion