Swift AVFoundation翻转摄像头的功能不起作用

8ehkhllq  于 12个月前  发布在  Swift
关注(0)|答案(1)|浏览(123)

我在下面有一个功能,可以在前后摄像头之间切换。下面的这个功能可以工作,但是我必须点击两次按钮才能调用这个功能,摄像头才能真正翻转。我尝试调试这个问题,但是不知道为什么翻转只在第二次尝试时才起作用。我不太确定为什么会话会这样。

func flipCamera() {
        guard let currentVideoInput = session.inputs.first as? AVCaptureDeviceInput else {
            return
        }

        session.beginConfiguration()
        session.removeInput(currentVideoInput)

        let newCameraPosition: AVCaptureDevice.Position = (currentCameraPosition == .back) ? .front : .back
        guard let newCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: newCameraPosition) else {
            session.commitConfiguration()
            return
        }

        do {
            let newVideoInput = try AVCaptureDeviceInput(device: newCamera)

            if session.canAddInput(newVideoInput) {
                session.addInput(newVideoInput)
                currentCameraPosition = newCameraPosition
            } else {
                session.addInput(currentVideoInput) // Re-add the old input if new input fails
            }
        } catch {
            print("Error creating new camera input: \(error)")
            session.addInput(currentVideoInput) // Re-add the old input in case of error
        }

        session.commitConfiguration()
    }

字符串
更新代码。不要只删除第一个输入,而是删除所有的arnt音频:

session.inputs.forEach { input in
    if let deviceInput = input as? AVCaptureDeviceInput {
        let device = deviceInput.device
        
        if !device.hasMediaType(.audio) {
            session.removeInput(input)
        }
    }
}

plicqrtu

plicqrtu1#

OP ahmed在评论中提到:
这是因为我的会话也有一个音频输入,在设置过程中,它位于会话inputs数组的索引1,而相机是第一个索引。
所以在第一次尝试删除摄像头输入工程,但随后音频是在第一个索引和新的摄像头是在第二个索引

session.inputs.forEach { input in
    if let deviceInput = input as? AVCaptureDeviceInput {
        let device = deviceInput.device
        
        if !device.hasMediaType(.audio) {
            session.removeInput(input)
        }
    }
}

字符串
原始答案:
您可能需要更新currentCameraPosition * 才能 * 尝试切换相机,因为seen here

func flipCamera() {
    guard let currentVideoInput = session.inputs.first as? AVCaptureDeviceInput else {
        print("Error: Could not find current video input.")
        return
    }

    currentCameraPosition = (currentCameraPosition == .back) ? .front : .back

    session.beginConfiguration()
    session.removeInput(currentVideoInput)

    guard let newCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: currentCameraPosition) else {
        print("Error: Could not find a camera for the requested position: \(currentCameraPosition).")
        session.commitConfiguration()
        return
    }

    do {
        let newVideoInput = try AVCaptureDeviceInput(device: newCamera)

        if session.canAddInput(newVideoInput) {
            session.addInput(newVideoInput)
        } else {
            print("Error: Cannot add new video input to the session.")
            currentCameraPosition = (currentCameraPosition == .back) ? .front : .back
            session.addInput(currentVideoInput) // Re-add the old input
        }
    } catch {
        print("Error creating new camera input: \(error)")
        currentCameraPosition = (currentCameraPosition == .back) ? .front : .back
        session.addInput(currentVideoInput) // Re-add the old input
    }

    session.commitConfiguration()
}


我添加了一些日志/错误处理,以便更好地确定功能失败的时间。currentCameraPosition在方法开始时更新。如果添加新输入失败或发生错误,currentCameraPosition将恢复到以前的状态。
session.canAddInput(newVideoInput)失败,旧的输入被重新添加。我尝试将canAddInput函数 Package 在一个调度队列中,由于进程是异步的,因此该队列的运行有几秒钟的延迟,但这并没有解决问题。
此外,相机总是成功的第一次尝试时翻转。但它失败后,只有第二次尝试的每一个相机翻转工作。
session.canAddInput(newVideoInput)在第一次尝试时失败但在第二次尝试时成功的行为可能是由于在调用canAddInput时会话仍在更新其配置的过程中。
由于这些操作是异步的,会话可能不会在删除旧输入后立即准备好接受新输入。
考虑到添加延迟并不能解决这个问题,并且考虑到session.canAddInput(newVideoInput)在第一次尝试时失败但在第二次尝试时成功的行为,这个问题可能并不完全与时间或会话配置的异步性质有关。
一个潜在的问题可能与会话仍然保留以前输入的某些方面有关,从而阻止在第一次尝试时添加新输入。为了缓解此问题,您可以在添加新输入之前尝试更彻底地重置会话。这可能包括临时停止会话或显式清除输入和输出等步骤。

func flipCamera() {
    guard let currentVideoInput = session.inputs.first as? AVCaptureDeviceInput else {
        print("Error: Could not find current video input.")
        return
    }

    // Update camera position
    currentCameraPosition = (currentCameraPosition == .back) ? .front : .back

    // Attempt to reset the session more thoroughly
    session.beginConfiguration()
    session.removeInput(currentVideoInput)

    // Optionally, stop the session temporarily
    session.stopRunning()

    guard let newCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: currentCameraPosition) else {
        print("Error: Could not find a camera for the requested position: \(currentCameraPosition).")
        session.commitConfiguration()
        return
    }

    do {
        let newVideoInput = try AVCaptureDeviceInput(device: newCamera)

        // Start the session again before adding new input
        session.startRunning()

        if session.canAddInput(newVideoInput) {
            session.addInput(newVideoInput)
        } else {
            print("Error: Cannot add new video input to the session.")
            // Revert to previous state
            currentCameraPosition = (currentCameraPosition == .back) ? .front : .back
            session.addInput(currentVideoInput)
        }
    } catch {
        print("Error creating new camera input: \(error)")
        // Revert to previous state
        currentCameraPosition = (currentCameraPosition == .back) ? .front : .back
        session.addInput(currentVideoInput)
    }

    session.commitConfiguration()
}


在删除输入之前暂时停止与session.stopRunning()的会话,并在添加新输入之前使用session.startRunning()再次启动会话。这有助于清除与先前相机输入相关的任何延迟状态。Committing the session configuration在尝试添加新输入后完成。

相关问题