iOS录屏时背景音频与麦克风混音异常排查
iOS视频录制应用麦克风失效问题排查与修复
问题根源
你遇到的控制台错误AVAudioSession_iOS.mm:1271 Deactivating an audio session that has running I/O,本质是音频会话在仍有活跃的输入/输出操作时被强制停用。加上你采用的“录制时添加麦克风输入、停止时移除”的动态方案,没有正确同步AVCaptureSession与AVAudioSession的状态,导致麦克风资源未被正确释放,后续无法重新启用。
核心修复方案
方案一:初始化时配置音频会话(推荐,避免动态增删的状态问题)
不用等到录制时才添加麦克风输入,通过配置音频会话的Category和选项,直接实现背景音频与麦克风录制共存,从根源解决初始打断背景音频的问题:
- 配置AVAudioSession
// 在CameraViewModel初始化或相机页面加载时执行 do { let audioSession = AVAudioSession.sharedInstance() // 使用.playAndRecord允许同时播放音频和录制麦克风 // 添加.mixWithOthers选项,避免打断正在播放的背景音频 // .allowBluetooth为可选配置,支持蓝牙音频设备 try audioSession.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth]) try audioSession.setActive(true) } catch { print("音频会话配置失败:\(error.localizedDescription)") }
- 初始化AVCaptureSession时直接添加麦克风输入
func setupCaptureSession() { captureSession.beginConfiguration() // 添加相机视频输入 guard let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return } do { let videoInput = try AVCaptureDeviceInput(device: videoDevice) if captureSession.canAddInput(videoInput) { captureSession.addInput(videoInput) } } catch { print("视频输入添加失败:\(error)") } // 添加麦克风音频输入(初始化时直接添加,不再动态增删) guard let audioDevice = AVCaptureDevice.default(for: .audio) else { return } do { let audioInput = try AVCaptureDeviceInput(device: audioDevice) if captureSession.canAddInput(audioInput) { captureSession.addInput(audioInput) } } catch { print("音频输入添加失败:\(error)") } // 添加视频录制输出 let videoOutput = AVCaptureMovieFileOutput() if captureSession.canAddOutput(videoOutput) { captureSession.addOutput(videoOutput) } captureSession.commitConfiguration() }
方案二:修复动态增删麦克风输入的流程(若坚持原方案)
如果必须保留“录制时加、停止时删”的逻辑,必须严格保证会话状态同步,避免I/O冲突:
- 开始录制时的流程
func startRecording() { // 先停止会话,再修改输入 captureSession.stopRunning() captureSession.beginConfiguration() // 添加麦克风输入 guard let audioDevice = AVCaptureDevice.default(for: .audio) else { return } do { let audioInput = try AVCaptureDeviceInput(device: audioDevice) if captureSession.canAddInput(audioInput) { captureSession.addInput(audioInput) } } catch { print("添加麦克风输入失败:\(error)") } captureSession.commitConfiguration() captureSession.startRunning() // 启动AVCaptureMovieFileOutput的录制逻辑 guard let movieOutput = captureSession.outputs.first as? AVCaptureMovieFileOutput else { return } let outputURL = // 你的录制文件URL movieOutput.startRecording(to: outputURL, recordingDelegate: self) }
- 停止录制时的流程
func stopRecording() { // 先停止录制写入 guard let movieOutput = captureSession.outputs.first as? AVCaptureMovieFileOutput else { return } if movieOutput.isRecording { movieOutput.stopRecording() } // 停止会话后再移除麦克风输入 captureSession.stopRunning() captureSession.beginConfiguration() // 移除所有音频输入 if let audioInput = captureSession.inputs.first(where: { $0.mediaType == .audio }) { captureSession.removeInput(audioInput) } captureSession.commitConfiguration() captureSession.startRunning() // 切换音频会话回播放模式,保证背景音频正常 do { let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(.playback, mode: .default) try audioSession.setActive(true) } catch { print("音频会话切换失败:\(error)") } }
关键注意事项
- 音频会话的
mixWithOthers选项是核心:没有这个选项时,.playAndRecord会默认打断其他音频播放,这是你最初初始化麦克风时背景音频停止的原因。 - 修改
AVCaptureSession的输入输出必须在beginConfiguration()和commitConfiguration()之间,且必须保证会话处于停止状态,否则会引发资源占用冲突。 - 停用音频会话前,必须确保所有相关I/O操作(比如录制写入、麦克风捕获)已完全停止,否则就会触发你遇到的错误。
内容的提问来源于stack exchange,提问作者krish
相关产品推荐
相关产品推荐

