You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

分段控件切换至视频时相机预览层无法显示问题求助

相机App录像模式无法显示预览画面排查方案

我开发的相机App通过分段控件切换拍照和录像模式,拍照ViewController能正常显示视频流,但切换到VideoViewController时,只能看到设置了背景色的PreviewLayer,无法呈现相机预览画面。

相关代码

class VideoViewController: UIViewController {
    
    var isRecording: Bool = false
    private var permissionGranted = false
    var videoSession = AVCaptureSession()
    
    var captureSession = AVCaptureSession()
    var movieOutput = AVCaptureMovieFileOutput()
    let captureSessionQueue = DispatchQueue(label: "captureSessionQueue")
    
    let previewLayer = AVCaptureVideoPreviewLayer()

override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .blue
        view.layer.addSublayer(previewLayer)
        previewLayer.backgroundColor = UIColor.systemPink.cgColor

        view.addSubview(startVideoButton)
        view.addSubview(stopVideoButton)
        stopVideoButton.isHidden = true
        
        startVideoButton.addTarget(self, action: #selector(startRecording), for: .touchUpInside)
        
        stopVideoButton.addTarget(self, action: #selector(stopRecording), for: .touchUpInside)

        checkCameraPermissions()
    }

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        previewLayer.frame = view.bounds

        startVideoButton.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height - 80)
        
        stopVideoButton.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height - 80)
    }

private func setUpVideoCamera() {
        guard permissionGranted else { return }
        videoSession.beginConfiguration()
        videoSession.sessionPreset = .high

        let camera = AVCaptureDevice.default(for: .video)
        let cameraInput: AVCaptureDeviceInput
        do {
            cameraInput = try AVCaptureDeviceInput(device: camera!)
        } catch {
            print("Error setting device video input: \(error)")
            return
        }

        if videoSession.canAddInput(cameraInput) {
            videoSession.addInput(cameraInput)
        }

        if videoSession.canAddOutput(movieOutput) {
            videoSession.addOutput(movieOutput)
        }
        
        previewLayer.videoGravity = .resizeAspectFill
        previewLayer.session = videoSession
        videoSession.startRunning()
        
        // Add audio device
        
        do {
            let audioDevice = AVCaptureDevice.default(for: .audio)
            let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice!)

            if videoSession.canAddInput(audioDeviceInput) {
                videoSession.addInput(audioDeviceInput)
            } else {
                print("Could not add audio device input to the session")
            }
        } catch {
            print("Could not create audio device input: \(error)")
        }
        
    }

模拟器截图

录像页仅显示PreviewLayer背景色
录像页按钮显示状态

问题排查与修复建议

  • 缺失配置提交:setUpVideoCamera中调用了videoSession.beginConfiguration()但未执行videoSession.commitConfiguration(),导致所有Session配置无法生效。需在添加完所有输入输出后补充这行代码:

    videoSession.commitConfiguration()
    
  • Session操作未在专用队列执行:AVCaptureSession的配置、启动属于耗时操作,必须放在专用串行队列captureSessionQueue中执行,避免主线程阻塞和线程安全问题。修改权限检查后的调用逻辑:

    // 示例权限检查逻辑,需确保授权成功后在队列中启动配置
    private func checkCameraPermissions() {
        AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
            DispatchQueue.main.async {
                self?.permissionGranted = granted
                if granted {
                    self?.captureSessionQueue.async {
                        self?.setUpVideoCamera()
                    }
                }
            }
        }
    }
    

    同时调整setUpVideoCamera中Session启动的顺序,确保先提交配置再启动Session。

  • 冗余Session变量:代码中同时定义了videoSession和captureSession,但实际仅使用videoSession,建议删除无用的captureSession变量,避免逻辑混淆。

  • 确认权限触发逻辑:检查checkCameraPermissions方法,确保用户授权相机权限后,正确调用了setUpVideoCamera,否则相机配置逻辑不会被触发。

内容的提问来源于stack exchange,提问作者aliufemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:10:31