RealityKit or SceneKit

RealityKit

import UIKit
import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()
        
        // Add the box anchor to the scene
        arView.scene.anchors.append(boxAnchor)
    }
}

SceneKit

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        // Set the scene to the view
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }

    // MARK: - ARSCNViewDelegate
    
/*
    // Override to create and configure nodes for anchors added to the view's session.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
     
        return node
    }
*/
    
    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        
    }
    
    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
        
    }
    
    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
        
    }
}

Type ‘MLModel’ has no member ‘__loadContents’ error on xcode 12

Reference

https://stackoverflow.com/questions/63917164/ml-build-error-for-catalyst-xcode-12-gm

Symptom

Type ‘MLModel’ has no member ‘__loadContents’ error occurred on Xcode 12

Cause

CoreML compiler in Xcode 12.0 GM is generating code that has symbols available only on macOS BigSur causing the compilation issue. If the goal is to build a catalyst or macOS-only app with Xcode 12.0

Solution

  1. In your targets build settings you can set COREML_CODEGEN_LANGUAGE to “None”
  2. Open terminal then go to where your .mlmodel folder
  3. Type “xcrun coremlcompiler generate <YourModel.mlmodel> –language Swift .”
  4. This will create <YourModel.swift> file in same folder.
  5. Open Xcode and add <YourModel.swift> in your project.
  6. Click <YourModel.swift> and comment out method that compiler complains.

In my case, I commented out the following two functions, recompiled the project again and it worked fine.

//    class func load(configuration: MLModelConfiguration = MLModelConfiguration(), completionHandler handler: @escaping (Swift.Result<CatDog100, 

//    class func load(contentsOf modelURL: URL, configuration: MLModelConfiguration = MLModelConfiguration(), completionHandler handler: @escaping (Swift.Result<CatDog100, Error>) -> Void) {

framework related errors

No such module ‘framework名’

症状

コンパイル時に、No such module ‘framework名’のエラー

原因

framework のサーチパスが設定されていない可能性がある。

対応

Build Settings >> Search Paths >> Framework Search Paths のパスを正しく設定する。

この時、TestFoundation.framework という名前の場合、TestFoundation.framework の1つ上のディレクトリを指定する。

例 Debug の iphonesimulator の場合
***/Build/Products/Debug-iphonesimulator/TestFoundation.framework
であれば、
***/Build/Products/Debug-iphonesimulator
になる。

framework の種類が、Debug/Release, iphoneos/iphonesimulator により、パスが異なってくるので、正しいパスを設定する。

Could not find module ‘フレームワーク名’ for target ‘arm64-apple-ios’; found: x86_64-apple-ios-simulator, x86_64

症状

Could not find module ‘フレームワーク名’ for target ‘arm64-apple-ios’; found: x86_64-apple-ios-simulator, x86_64

原因

framework のサーチパスが シミュレータ用にビルドされたフレームワークのパスに設定されている。

対応

Build Settings >> Search Paths >> Framework Search Paths のパスを正しく設定する。

この時、TestFoundation.framework という名前の場合、TestFoundation.framework の1つ上のディレクトリを指定する。

例 Debug の iphonesimulator の場合
***/Build/Products/Debug-iphoneos/TestFoundation.framework
であれば、
***/Build/Products/Debug-iphoneosになる。

framework の種類が、Debug/Release, iphoneos/iphonesimulator により、パスが異なってくるので、正しいパスを設定する。

Building for iOS, but the linked and embedded framework

症状

iOS 用でフレームワークを含むプロジェクトをコンパイル時に、次のエラー。

プロジェクトパス Building for iOS, but the linked and embedded framework ‘フレームワーク名.framework’ was built for iOS Simulator.

原因

iOS (実機)用にビルドしたが、埋め込まれたフレームワークが iOS シミュレータ用にビルドされている。

対応

Build Settings >> Search Paths >> Framework Search Paths のパスを正しく設定する。1つ上のエラーへの対応方法を参照。

signal SIGABORT

症状

dyld: Library not loaded: @rpath/TestFoundation.framework/TestFoundation

  Referenced from: /Users/uchukamen/Library/Developer/CoreSimulator/Devices/255ADD3E-7C65-4B7E-B2C6-A2F3458C7F13/data/Containers/Bundle/Application/8F3B69D4-05EE-4128-A34D-E85A6D7CEE96/CallFramework.app/CallFramework

  Reason: image not found

dyld: launch, loading dependent libraries

DYLD_SHARED_CACHE_DIR=/Users/uchukamen/Library/Developer/CoreSimulator/Caches/dyld/19G2021/com.apple.CoreSimulator.SimRuntime.iOS-14-0.18A372

DYLD_ROOT_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot

DYLD_LIBRARY_PATH=/Users/uchukamen/Library/Developer/Xcode/DerivedData/CallFramework-cbztckdabgiykdcxvrwnezepshbh/Build/Products/Debug-iphonesimulator:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/introspection

DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libBacktraceRecording.dylib:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Develo

原因

プロジェクトから、framework が削除されれた。

対応

プロジェクトに、framework を追加する。

関連情報

SwiftでFramework(ライブラリ)を作成、利用する方法

Xcodeでフレームワークを追加する方法【初心者向け】

Swiftの汎用的なモジュール(Framework)開発

独自のライブラリ(.framework)を組み込んで苦労した話

unable to find utility “xcodebuild”

Symptom

$ carthage update

*** Fetching iCimulator

*** Checking out iCimulator at “1.5”

*** xcodebuild output can be found in /var/folders/gm/t2l4p33d1r9gpqzscb8kdggw0000gn/T/carthage-xcodebuild.vQIFtO.log

A shell task (/usr/bin/xcrun xcodebuild -workspace /Users/uchukamen/Desktop/Swift/NegaViewer/NegaViewerV1.1.1/Carthage/Checkouts/iCimulator/iCimulator.xcworkspace CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES -list) failed with exit code 72:

xcrun: error: unable to find utility “xcodebuild”, not a developer tool or in PATH

Solution

xcode menu >> “xcode” >> preferences >> Location >> Comand Line Tools で値を設定

Check “Command Line Tools” is not “”.

A beautiful sea of clouds at Chichibu, Japan.

This video has been remixed from Chichi Live Camera photos by Python + OpenCV + Visual Studio Code on mac.

import os
import time
import datetime
import urllib.error
import urllib.request
import cv2

def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file:
            data = web_file.read()
            with open(dst_path, mode='wb') as local_file:
                local_file.write(data)
    except urllib.error.URLError as e:
        print(e)

fourcc = cv2.VideoWriter_fourcc(* 'h264')
fps = 10
out = cv2.VideoWriter('out.mp4', fourcc, fps, (H,V))

startTime = datetime.datetime(yyyy, mm, dd, HH, MM, SS)
x = duration
for interval in range(x):
    t = startTime + datetime.timedelta(minutes=interval)
    print(datetime.datetime.strftime(t, "/%Y%m%d/%H%M%S.jpg"))
    tstr = datetime.datetime.strftime(t, "/%Y%m%d/%H%M%S.jpg")
    url = 'https://*********' + tstr
    dst_path = datetime.datetime.strftime(t, "images/%Y%m%d%H%M%S.jpg")
    if os.path.exists(dst_path):
        print("skip")
    else:
        download_file(url, dst_path)
        time.sleep(10)  # Don't rush to 

    img = cv2.imread(dst_path, cv2.IMREAD_COLOR)
    # 画像の大きさを取得
    # height, width, channels = img.shape[:3]
    # print("width: " + str(width))
    # print("height: " + str(height))
    out.write(img)

out.release()

Chichibu Live Camera

You can find out beautiful photos of Chichibu Live camera from here.

https://navi.city.chichibu.lg.jp/cloudview/

Anohana: The Flower We Saw That Day

Chichibu is also famous for the animation Anohana: The Flower We Saw That Day. It was on air in 2011, but still may anime fans are visiting Chichibu, the place of anime scenes.

Class QMacAutoReleasePoolTracker is implemented in both warning.

Environment

macOS Catalina 10.15.6

mac Mini

OpenCV 4.4.0

Python 3.8

Visual Studio Code V1.48.2

Symptom


When I execute the previous article, TimeLapse, the following warnings appear in the terminal.

objc[3865]: Class QMacAutoReleasePoolTracker is implemented in both /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore (0x10a1e0a48) and /usr/local/lib/python3.8/site-packages/cv2/.dylibs/QtCore (0x10f5fe700). One of the two will be used. Which one is undefined.

objc[3865]: Class QT_ROOT_LEVEL_POOL__THESE_OBJECTS_WILL_BE_RELEASED_WHEN_QAPP_GOES_OUT_OF_SCOPE is implemented in both /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore (0x10a1e0ac0) and /usr/local/lib/python3.8/site-packages/cv2/.dylibs/QtCore (0x10f5fe778). One of the two will be used. Which one is undefined.


objc[3865]: Class KeyValueObserver is implemented in both /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore (0x10a1e0ae8) and /usr/local/lib/python3.8/site-packages/cv2/.dylibs/QtCore (0x10f5fe7a0). One of the two will be used. Which one is undefined.


objc[3865]: Class RunLoopModeTracker is implemented in both /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore (0x10a1e0b38) and /usr/local/lib/python3.8/site-packages/cv2/.dylibs/QtCore (0x10f5fe7f0). One of the two will be used. Which one is undefined.

Workaround

$ pip uninstall opencv-python

$ pip install opencv-python-headless

Special Thanks To

https://qiita.com/LemniscaterN/items/dfcda303677ca2ebf049

https://pypi.org/project/opencv-python/

TimeLapse by mac Mini + OpenCV + Python

Environment

macOS Catalina 10.15.6

OpenCV

Python 3.8

Tyhoon HAISHEN is coming!

Source Code

import cv2

RATE = 30
cap = cv2.VideoCapture(0)
w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*'h264')
out = cv2.VideoWriter('out.mp4', fourcc, fps, (int(w), int(h)))

count = RATE
while True:
    ret, frame = cap.read()
    if ret == True:
        if count == 0:
            out.write(frame)
            count = RATE
        count -= 1
        cv2.imshow('frame', frame)
        keyboard = cv2.waitKey(30)
        if keyboard == 27:
            break
    else:
        break
cap.release()
out.release()
cv2.destroyAllWindows()

mac, VisualStudio Code, OpenCV, VideoCapture, Crash due to PRIVACY VIOLATION

現象 

mac OSで、Visual Studio Code で、次のコードを実行すると、クラッシュする。

import cv2
cap = cv2.VideoCapture(0) # ここで、Pythonがクラッシュする。

環境

Mac OS: Catalina 10.15.6

Visual Studio Code: 1.48.2

Python 3.8.4

原因

クラッシュレポートを見ると、次のようになっていて、

Crashed Thread: 1 Dispatch queue: com.apple.root.default-qos
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY

Thread 1 Crashed:: Dispatch queue: com.apple.root.default-qos

0x00007fff71fb4411 abort_with_payload + 9 3 com.apple.TCC 0x00007fff6868559f __CRASHING_DUE_TO_PRIVACY_VIOLATION + 163
4 com.apple.TCC 0x00007fff68683531 __TCCAccessRequest_block_invoke.114 + 500

CRASHING_DUE_TO_PRIVACY_VIOLATION

macOS 10.15 Catalinaでは「User Consent」がさらに強化され、アプリがスクリーンキャプチャの撮影や書類、ダウンロードフォルダへのアクセスする際にユーザーの承認が必要に。

Visual Studio Code が Python を実行する段階で、Permission を取得していないのが原因と思われる。

Workaround

調べた限りでは、解決策は見つからず、次のワークアラウンドしかない。

方法1

コマンドラインから、sudo で Visual Studio Codeを起動する。

$ sudo /Applications/Visual\ Studio\ Code.app/Contents/MacOS/Electron 

方法2

sudo /bin/bash でターミナルを起動し、Python を起動し、直接 実行する。

AV, In, Out, Session, Delegate

混乱するので、まとめ。

種別InputOutputDelegateDelegate
CameraAVCaptureDevice videoAVCapture
PhotoOutput
AVCapture
PhotoCaptureDelegate
photoOutput
LivePhotoAVCaptureDevice video, audioAVCapture
PhotoOutput
AVCapture
PhotoCaptureDelegate
capturePhoto
VideoAVCaptureDevice video, audioAVCapture
MovieFileOutput
AVCapture
FileOutputRecordingDelegate
fileOutput
Face
Detection
AVCaptureDevice videoAVCapture
VideoDataOutput
AVCapture
VideoDataOutputSampleBufferDelegate

ライブフォトのキャプチャと保存

オリジナル情報源

https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/capturing_still_and_live_photos/capturing_and_saving_live_photos

概要

ライブフォトは、キャプチャの直前と直後の瞬間のモーションとサウンドを含む写真です。アプリは、AVFoundationキャプチャシステムとAVCapturePhotoOutputクラスを使用して、ライブフォトをキャプチャして記録できます。

注意

すでにキャプチャセッション、入力設定、および写真撮影に慣れていない場合は、参照キャプチャセッションの設定とキャプチャとライブ写真。

ライブ写真キャプチャを有効にする

静止写真の場合、キャプチャセッションにはビデオ入力のみが必要ですが、ライブフォトにはサウンドが含まれているため、オーディオキャプチャデバイスをセッションに接続する必要もあります。

enum CameraError: Error {
    case configurationFailed
    // ... additional error cases ...
}

func configureSession() throws {
    captureSession.beginConfiguration()
    
    // ... add camera input and photo output ...
    
    guard let audioDevice = AVCaptureDevice.default(for: .audio),
          let audioDeviceInput = try? AVCaptureDeviceInput(device: audioDevice) else {
              throw CameraError.configurationFailed
    }
    
    if captureSession.canAddInput(audioDeviceInput) {
        captureSession.addInput(audioDeviceInput)
    } else {
        throw CameraError.configurationFailed
    }
    
    // ... configure photo output and start running ...
    
    captureSession.commitConfiguration()
}

ビデオに組み込みのカメラデバイスを既に使用しているため(「キャプチャセッションの設定」を参照)、デフォルトのオーディオキャプチャデバイスを使用できます。システムは、カメラの位置に最適なマイク構成を自動的に使用します。

Live Photosをキャプチャするには、キャプチャパイプラインの内部再構成が必要です。これには時間がかかり、進行中のキャプチャが中断されます。最初のライブ写真を撮影する前に、AVCapturePhotoOutputオブジェクトでライブ写真のキャプチャを有効にして、パイプラインが適切に構成されていることを確認してください。

let photoOutput = AVCapturePhotoOutput()

// Attempt to add the photo output to the session.
if captureSession.canAddOutput(photoOutput) {
    captureSession.sessionPreset = .photo
    captureSession.addOutput(photoOutput)
} else {
    throw CameraError.configurationFailed
}

// Configure the photo output's behavior.
photoOutput.isHighResolutionCaptureEnabled = true
photoOutput.isLivePhotoCaptureEnabled = photoOutput.isLivePhotoCaptureSupported

// Start the capture session.
captureSession.startRunning()

ライブ写真をキャプチャ

写真出力がLive Photosの準備ができたら、各ショットの静止画像またはLive Photoキャプチャを選択できます。ライブフォトをキャプチャするにはAVCapturePhotoSettingsオブジェクトを作成し、ライブフォトの静止画部分の形式を選択し、ライブフォトのムービー部分を書き込むためのURLを提供します。次に、キャプチャをトリガーするためにcapturePhoto(with:delegate:)を呼び出します:

let photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc])
photoSettings.livePhotoMovieFileURL = // output url

// Shoot the Live Photo, using a custom class to handle capture delegate callbacks.
let captureProcessor = LivePhotoCaptureProcessor()
photoOutput.capturePhoto(with: photoSettings, delegate: captureProcessor)

ライブ写真の結果を処理する

ライブフォトは、写真アプリでは1つのアセットとしてユーザーに表示されますが、実際には、メインの静止画像と、前後の瞬間のモーションとサウンドを含むムービーファイルの別々のファイルで構成されています。キャプチャシステムは、それぞれが利用可能になるとすぐに、これらの結果を個別に配信します。

このphotoOutput(_:didFinishProcessingPhoto:error:)メソッドは、Live Photoの静止画部分をAVCapturePhotoオブジェクトとして配信します。静止画像と動画ファイルを一緒に保存する必要があるため、以下から示すように、画像ファイルのデータをAVCapturePhotoから抽出し、動画ファイルの記録が完了するまで保持することをお勧めします。(このメソッドを使用して、UIで静止画像がキャプチャされたことを示すこともできます。)

func photoOutput(_ output: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photo: AVCapturePhoto,
                 error: Error?) {
    guard error != nil else {
        print("Error capturing Live Photo still: \(error!)");
        return
    }
    
    // Get and process the captured image data.
    processImage(photo.fileDataRepresentation())
}

このphotoOutput(_:didFinishProcessingLivePhotoToMovieFileAt:duration:photoDisplayTime:resolvedSettings:error:)メソッドは後で起動し、キャプチャのトリガー時に指定したURLに完全なムービーファイルが含まれていることを示します。ライブ写真の静止画と動画の両方の部分を取得したら、それらを一緒に保存できます。

func photoOutput(_ output: AVCapturePhotoOutput,
                 didFinishProcessingLivePhotoToMovieFileAt outputFileURL: URL,
                 duration: CMTime,
                 photoDisplayTime: CMTime,
                 resolvedSettings: AVCaptureResolvedPhotoSettings,
                 error: Error?) {
    
    guard error != nil else {
        print("Error capturing Live Photo movie: \(error!)");
        return
    }
    
    guard let stillImageData = stillImageData else { return }
    
    // Save Live Photo.
    saveLivePhotoToPhotosLibrary(stillImageData: stillImageData,
                                 livePhotoMovieURL: outputFileURL)
}

注意

キャプチャ後にLive Photosを表示するには、PHLivePhotoおよびPHLivePhotoViewを参照してください。

ライブ写真をフォトライブラリに保存する

PHAssetCreationRequestクラスを使用して、複数のファイルのメディアで構成される単一のPhotosアセットを作成します。LivePhotoの場合、静止画像とそのペアのビデオです。キャプチャした写真の保存と同様に、そのリクエストをPHPhotoLibrary変更ブロックでラップし、最初にアプリが写真にアクセスするユーザーの権限を持っていることを確認する必要があります。

func saveLivePhotoToPhotosLibrary(stillImageData: Data, livePhotoMovieURL: URL) {    PHPhotoLibrary.requestAuthorization { status in
        guard status == .authorized else { return }
        
        PHPhotoLibrary.shared().performChanges({
            // Add the captured photo's file data as the main resource for the Photos asset.
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .photo, data: stillImageData, options: nil)
            
            // Add the movie file URL as the Live Photo's paired video resource.
            let options = PHAssetResourceCreationOptions()
            options.shouldMoveFile = true
            creationRequest.addResource(with: .pairedVideo, fileURL: livePhotoMovieURL, options: options)
        }) { success, error in
            // Handle completion.
        }
    }
}

ヒント

このshouldMoveFileオプションを使用して、iOSがアプリのサンドボックスからシステムのフォトライブラリにムービーファイルを転送します。高価なデータのコピー操作は必要ありません。

ライブ写真の進行状況を追跡する

Live Photosをキャプチャすると、「写真キャプチャの進行状況の追跡」に示すプロセスに2つの追加ステップが追加されます。静止画の結果の配信(ステップ4)の後、写真出力はムービーキャプチャステータスを通知し(ステップ5)、ムービー結果を配信します(ステップ6) )。(最終クリーンアップはステップ7になります。)

capturePhoto()を呼び出した後の番号付きのLive Photoキャプチャプロセスステップの図。

ユーザーがシステムのカメラアプリでライブ写真をキャプチャすると、「ライブ」インジケーターが数秒間表示され、ビデオとオーディオがまだ記録されていることをユーザーに知らせます。アプリに同様のインターフェイスを提供するには、写真キャプチャデリゲートに次のメソッドを実装します。

複数のライブフォトキャプチャを同時に実行できるため、これらの方法を使用して、「処理中」のキャプチャの数を追跡し、その数がゼロに達した場合にのみインジケータを非表示にするのが最善です。

class LivePhotoCaptureProcessor: NSObject, AVCapturePhotoCaptureDelegate {
    // ... other PhotoCaptureDelegate methods and supporting properties ...
    
    // A handler to call when Live Photo capture begins and ends.
    var livePhotoStatusHandler: (Bool) -> () = { _ in }
    
    // A property for tracking in-progress captures and updating UI accordingly.
    var livePhotosInProgress = 0 {
        didSet {
            // Update the UI accordingly based on the value of this property
        }
    }
    
    // Call the handler when PhotoCaptureDelegate methods indicate Live Photo capture is in progress.
    func photoOutput(_ output: AVCapturePhotoOutput,
                     willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
        let capturingLivePhoto = (resolvedSettings.livePhotoMovieDimensions.width > 0 && resolvedSettings.livePhotoMovieDimensions.height > 0)
        livePhotoStatusHandler(capturingLivePhoto)
    }
    
    func photoOutput(_ output: AVCapturePhotoOutput,
                     didFinishRecordingLivePhotoMovieForEventualFileAt outputFileURL: URL,
                     resolvedSettings: AVCaptureResolvedPhotoSettings) {
        livePhotoStatusHandler(false)
    }
}