AVFoundation 相机在 Swift 中发布

问题描述 投票:0回答:1

我有一个使用 AVFoundation 和 Swift 构建的自定义相机。当相机启动时,它最初会放大。大约一秒钟后,它会缩小到正常状态。我不确定为什么会发生这种情况,我根本不修改放大倍数,也不更改输入相机。也许我的 setup() 函数有问题。

struct CameraPreview: UIViewRepresentable {
   @EnvironmentObject var cameraModel : CameraViewModel
   var size: CGSize
   
   func makeUIView(context: Context) -> UIView {
       let view = UIView(frame: CGRect(origin: .zero, size: size))
       guard let preview = cameraModel.preview else { return view }

       preview.frame = view.bounds
       preview.videoGravity = .resizeAspectFill
       view.layer.addSublayer(preview)

       DispatchQueue.global(qos: .userInitiated).async {
           if !self.cameraModel.session.isRunning {
               self.cameraModel.session.startRunning()
           }
       }
       
       return view
   }
   
   func updateUIView(_ uiView: UIView, context: Context) { }
}


class CameraViewModel: NSObject, ObservableObject, AVCaptureFileOutputRecordingDelegate, AVCapturePhotoCaptureDelegate {
   @Published var session = AVCaptureSession()
   @Published var alert = false
   @Published var output = AVCaptureMovieFileOutput()
   @Published var preview: AVCaptureVideoPreviewLayer!
   @Published var isRecording: Bool = false
   @Published var recordedURLs: [URL] = []
   @Published var previewURL: URL?
   @Published var showPreview: Bool = false
   @Published var recordedDuration: CGFloat = 0
   @Published var maxDuration: CGFloat = 25
   @Published var capturedImage: UIImage?
   @Published var photoOutput = AVCapturePhotoOutput()
   @Published var flashMode: AVCaptureDevice.TorchMode = .off
   var currentCameraPosition: AVCaptureDevice.Position = .back
   @Published var photoMode: Bool = true
   @Published var isVideoFlashOn: Bool = false
   
   override init() {
       super.init()
       self.checkPermission()
       self.preview = AVCaptureVideoPreviewLayer(session: session)
       self.preview.videoGravity = .resizeAspectFill
   }
   
   func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

   }
   
   func checkPermission(){
       switch AVCaptureDevice.authorizationStatus(for: .video) {
       case .authorized:
           checkAudioPermission()
           return
       case .notDetermined:
           AVCaptureDevice.requestAccess(for: .video) { (status) in
               if status {
                   self.checkAudioPermission()
               }
           }
       case .denied:
           self.alert.toggle()
           return
       default:
           return
       }
   }
   
   func checkAudioPermission() {
       switch AVCaptureDevice.authorizationStatus(for: .audio) {
       case .authorized:
           setUp()
           return
       case .notDetermined:
           AVCaptureDevice.requestAccess(for: .audio) { (audioStatus) in
               if audioStatus {
                   self.setUp()
               }
           }
       case .denied:
           self.alert.toggle()
           return
       default:
           return
       }
   }
   
   func setUp(){
       do {
           self.session.beginConfiguration()
           let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
           let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
           let audioDevice = AVCaptureDevice.default(for: .audio)
           let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
           
           if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
               self.session.addInput(videoInput)
               self.session.addInput(audioInput)
           }

           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 fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

   }
}
ios swift swiftui avfoundation
1个回答
0
投票

这可能与

AVCaptureSession
AVCaptureDevice
的配置有关。

您可以尝试在会话开始时明确设置相机的缩放级别。如果支持缩放,可以通过调整

videoZoomFactor
AVCaptureDevice
属性来完成。

您的

setUp
功能将是:

func setUp(){
    do {
        self.session.beginConfiguration()
        let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
        let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
        let audioDevice = AVCaptureDevice.default(for: .audio)
        let audioInput = try AVCaptureDeviceInput(device: audioDevice!)

        if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
            self.session.addInput(videoInput)
            self.session.addInput(audioInput)
        }

        if self.session.canAddOutput(self.output){
            self.session.addOutput(self.output)
        }

        if self.session.canAddOutput(self.photoOutput) {
            self.session.addOutput(self.photoOutput)
        }

        // Setting zoom level
        try cameraDevice?.lockForConfiguration()
        if cameraDevice?.activeFormat.videoMaxZoomFactor ?? 1 > 1 {
            cameraDevice?.videoZoomFactor = 1 // Set this to your desired zoom level
        }
        cameraDevice?.unlockForConfiguration()

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

我添加了一项检查以确保相机设备支持缩放,然后将

videoZoomFactor
设置为 1,这是正常的缩放级别。您可以根据需要调整该值。

请注意,操作

videoZoomFactor
需要锁定摄像头设备的配置,这就是使用
lockForConfiguration()
unlockForConfiguration()
的原因。

© www.soinside.com 2019 - 2024. All rights reserved.