Having trouble with flipping camera in swiftui / avfoundation / AVCaptureDeviceInput

440 Views Asked by At

I am coding a camera with swiftui using avfoundation and was able to get the setup to work as intended. However, as I'm implementing a flip camera functionality I'm running into an error where after flipping it just goes to a black screen as I'm assuming the input gets removed but the correct flipped input doesn't get shown:

Here is my code

class CameraViewModel: NSObject,ObservableObject,AVCaptureFileOutputRecordingDelegate, AVCapturePhotoCaptureDelegate{

 ... 
    @Published var session = AVCaptureSession()

 @objc dynamic var videoDeviceInput: AVCaptureDeviceInput!
    private let sessionQueue = DispatchQueue(label: "session queue")

 func setUp(){
        
        do{
            self.session.beginConfiguration()
            let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
            let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
            let audioDevice = AVCaptureDevice.default(for: .audio)
            let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
            
            // MARK: Audio Input
            
            if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
                self.session.addInput(videoInput)
                self.session.addInput(audioInput)
              self.videoDeviceInput = videoInput
            }

            if self.session.canAddOutput(self.output){
                self.session.addOutput(self.output)
            }
            if self.session.canAddOutput(self.photoOutput){
                self.session.addOutput(self.photoOutput)
            }
            
            self.session.commitConfiguration()
        }
        catch{
            print(error.localizedDescription)
        }
    }
  
    func changeCamera() {
      sessionQueue.async {
          if self.videoDeviceInput != nil {
              let currentVideoDevice = self.videoDeviceInput.device
              let currentPosition = currentVideoDevice.position
              
              let preferredPosition: AVCaptureDevice.Position
              
              switch currentPosition {
              case .unspecified, .front:
                  preferredPosition = .back
                  
              case .back:
                  preferredPosition = .front
                  
              @unknown default:
                  print("Unknown capture position. Defaulting to back, dual-camera.")
                  preferredPosition = .back
              }
            
            print("current pos is \(currentPosition.rawValue) and preferred position is \(preferredPosition.rawValue)")
              do{
                  self.session.beginConfiguration()
                
                //remove device as needed
                self.session.removeInput(self.videoDeviceInput)
                
                let newCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: preferredPosition)
                let newVideoInput = try AVCaptureDeviceInput(device: newCameraDevice!)
                let newAudioDevice = AVCaptureDevice.default(for: .audio)
                let newAudioInput = try AVCaptureDeviceInput(device: newAudioDevice!)
                
                // MARK: Audio Input
                
                if self.session.canAddInput(newVideoInput) && self.session.canAddInput(newAudioInput){
                    self.session.addInput(newVideoInput)
                    self.session.addInput(newAudioInput)
                  self.videoDeviceInput = newVideoInput
                }

                
                self.session.commitConfiguration()
                
              }catch{
                print(error.localizedDescription)
              }
          }
      }

    }
}

I'm not sure what I'm doing wrong as I've looked up previous stack overflow threads and online resources and all they say is to get the device input position and change that, remove it before committing configuration. Any help will be greatly appreciated!

Edit: I found the solution was to get rid of the audio input code as the audio is still being captured without it

1

There are 1 best solutions below

5
DatBlaueHus On

The problem is in the code you are not showing.

When you are displaying the Image in your SwiftUI view, the orientation depends on the used camera.

For the front camera, it is .upMirrored.

If you switch to use the back camera, you need to use .up.