AVFoundationでカメラの向きを変更するとライトが消えしまう問題

実行環境

Xcode:Version 13.2.1 (13C100)
Swiftのバージョン:Swift 5
DeploymentTargeted Device Families: iPhoneiOS Deployment Target: iOS 14.4

現象と解決策

AVFoundationでカメラの向きを変更するとライトが消えしまう問題に悩みました。より正確にいうと、AVCaptureConnectionのAVCaptureVideoOrientationを変更した時にライトが消えてしまう。
解決策は、ライトの設定をメインスレッドでする。

https://stackoverflow.com/questions/53657378/device-torch-turns-off-when-starting-avcapturesession

詳細な内容

例えば、以下のようなよくあるライトをOnにするサンプル。
呼び出したタイミングでは想定通りライトがつくと思います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func lightOn() {
// deviceはAVCaptureDevice?です。メンバーとして保持している前提
        if let device = device {
            do {
                try device.lockForConfiguration()
            } catch {
                return
            }
            // キャプチャデバイスにライトがあるか、 ライトが使用可能な状態か
            if device.hasTorch && device.isTorchAvailable {
                device.torchMode = .on
            }
            device.unlockForConfiguration()
        }
}

ただし、このままだとAVCaptureVideoOrientationに値をセットすると自動的にライトがオフにされてしまいます。


何が問題なんだろうと調べていると、冒頭のサイトに行き着きました。

どうもメインスレッドで設定する必要があるようです。

1
2
3
4
DispatchQueue.main.async {
 // ここに処理をかく
 self.lightOn()
}

これで画面の向きが変わってもライトオンにできるようになりました。

一点、注意点として、AVCaptureConnectionのAVCaptureVideoOrientationを設定した後にも呼び出さないといけないというところ。

つまり、以下のような処理があったとた場合、最後に再度ライトの設定をメインスレッドで実行する必要がありそうです。

1
2
3
4
5
6
7
8
9
10
11
func setOrientation(){
    for connection in videoDataOutput.connections {
        if connection.isVideoOrientationSupported {
            connection.videoOrientation = videoOrientation
        }
    }
    // connection.videoOrientationを変更するときはライトも再度設定
    DispatchQueue.main.async {
     self.lightOn()
    }
}

ん・・・なんだかなぁ。何か勘違いしているのかもしれない?

AVCaptureDeviceの設定はAVCaptureVideoOrientationに影響されるのか,それともライトだけなのかは今度確認していこう。

iOS, Swift

Posted by takumioda