macOS 15+下使用ScreenCaptureKit捕获麦克风输入失败求助
macOS 15.0+ 下 ScreenCaptureKit 无法捕获内置麦克风输入的解决方案
针对你遇到的屏幕视频捕获正常但内置麦克风无输入的问题,可从以下几个方向排查修复:
一、显式指定内置麦克风设备ID
尽管文档说明microphoneCaptureDeviceID = nil会使用默认设备,但 macOS 15+ 可能需要显式指定内置麦克风ID才能正常捕获。通过AVFoundation获取设备ID:
import AVFoundation func getBuiltInMicrophoneID() -> String? { let session = AVAudioSession.sharedInstance() guard let inputs = session.availableInputs else { return nil } return inputs.first(where: { $0.portType == .builtInMic })?.deviceID } // 初始化streamConfiguration时替换原设置 streamConfiguration.microphoneCaptureDeviceID = getBuiltInMicrophoneID()
注:AVFoundation/AVFAudio完全支持macOS,你之前的误解导致错过了这个关键方案。
二、调整SCStreamOutput添加逻辑
文件录制输出与手动添加的麦克风流输出可能存在冲突,简化流输出添加逻辑:
do { try stream.addStreamOutput(streamOutput, type: .screen, sampleHandlerQueue: videoSamplesQueue) try stream.addStreamOutput(streamOutput, type: .audio, sampleHandlerQueue: audioSamplesQueue) // 注释掉单独的.microphone类型添加,依赖streamConfiguration.captureMicrophone = true让录制输出自动包含麦克风音频 // try stream.addStreamOutput(streamOutput, type: .microphone, sampleHandlerQueue: microphoneSamplesQueue) stream.startCapture() logger.info("Started capturing...") } catch { logger.error("Unable to start capturing: \(error.localizedDescription)") }
三、主动验证并请求麦克风权限
即使Info.plist配置了权限,代码中仍需主动请求并确保用户授权:
import AVFoundation func requestMicrophonePermission() async -> Bool { let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playAndRecord, mode: .default) try session.setActive(true) } catch { print("Failed to set audio session: \(error)") return false } return await withCheckedContinuation { continuation in session.requestRecordPermission { granted in continuation.resume(returning: granted) } } } // 启动捕获前执行权限检查 let hasPermission = await requestMicrophonePermission() guard hasPermission else { logger.error("Microphone permission not granted") return }
四、完善recordingConfiguration配置
确保录制配置明确开启麦克风捕获,并设置音频编码参数:
let recordingConfiguration = SCStreamRecordingConfiguration(outputURL: URL(filePath: "some_file")) recordingConfiguration.audioCodec = .aac recordingConfiguration.videoCodec = .h264 recordingConfiguration.captureMicrophone = true // 与streamConfiguration保持一致,避免覆盖
五、检查CaptureEngineStreamOutput的样本处理逻辑
确保自定义输出类正确处理麦克风类型的样本,验证是否接收到数据:
class CaptureEngineStreamOutput: NSObject, SCStreamOutput { var capturedFrameHandler: ((CMSampleBuffer) -> Void)? var pcmBufferHandler: (AVAudioPCMBuffer) -> Void init(continuation: Any) { // 初始化逻辑 self.pcmBufferHandler = { _ in } super.init() } func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: capturedFrameHandler?(sampleBuffer) case .audio, .microphone: // 统一处理系统音频和麦克风音频,或区分处理 print("Received audio sample of type: \(type.rawValue)") if let pcmBuffer = sampleBuffer.toAudioPCMBuffer() { pcmBufferHandler(pcmBuffer) } default: break } } } extension CMSampleBuffer { func toAudioPCMBuffer() -> AVAudioPCMBuffer? { guard let formatDesc = CMSampleBufferGetFormatDescription(self), let audioFormat = AVAudioFormat(cmAudioFormatDescription: formatDesc) else { return nil } let sampleCount = CMItemCount(CMSampleBufferGetNumSamples(self)) guard let pcmBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: sampleCount) else { return nil } pcmBuffer.frameLength = sampleCount CMSampleBufferCopyPCMDataIntoAudioBufferList(self, atOffset: 0, frameCount: Int(sampleCount), into: pcmBuffer.mutableAudioBufferList) return pcmBuffer } }
如果控制台未打印麦克风类型的日志,说明流未输出麦克风数据,需回到配置层面重新检查;如果有日志但无有效数据,可能是设备硬件问题。
内容的提问来源于stack exchange,提问作者Vëx
相关产品推荐
相关产品推荐

