Swift/SwiftUI中如何录制设备播放声音并排除麦克风输入?
实现iOS设备内录(仅捕获播放音频,排除麦克风)的可行方案
方案1:使用AVCaptureSession(iOS 11+)
这是官方推荐的简洁方案,适配多数现代iOS设备:
- 配置
AVCaptureSession时,指定音频输入设备为AVCaptureDevice.default(.audioDataRecorder, for: .audio, position: .unspecified),该设备专门用于捕获设备内部播放的音频 - 添加
AVCaptureAudioDataOutput到会话,通过代理方法获取实时音频数据 - 启动会话后,在代理回调中处理捕获到的音频样本(写入文件或直接处理)
示例代码片段:
import AVFoundation class InternalAudioRecorder: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate { private let captureSession = AVCaptureSession() private let audioOutput = AVCaptureAudioDataOutput() func startInternalRecording() { guard let audioCaptureDevice = AVCaptureDevice.default(.audioDataRecorder, for: .audio, position: .unspecified) else { print("当前设备不支持音频内录") return } do { let audioInput = try AVCaptureDeviceInput(device: audioCaptureDevice) if captureSession.canAddInput(audioInput) { captureSession.addInput(audioInput) } if captureSession.canAddOutput(audioOutput) { captureSession.addOutput(audioOutput) let captureQueue = DispatchQueue(label: "com.audio.capture.queue") audioOutput.setSampleBufferDelegate(self, queue: captureQueue) } captureSession.startRunning() } catch { print("配置捕获会话失败:\(error.localizedDescription)") } } func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { // 处理捕获到的音频数据,示例:提取原始数据 guard let dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else { return } var totalLength = 0 var rawData: UnsafeMutablePointer<Int8>? CMBlockBufferGetDataPointer(dataBuffer, atOffset: 0, lengthAtOffsetOut: nil, totalLengthOut: &totalLength, dataPointerOut: &rawData) // 在此处将rawData写入文件或进行后续处理 } }
方案2:使用AudioToolbox(底层控制,兼容更早iOS版本)
若需支持iOS 11以下版本,或需要更精细的音频参数控制,可使用AudioToolbox框架:
- 通过
AudioObjectPropertyAddress查询系统内支持内录的音频设备ID - 配置
AudioQueue,指定输入设备为查询到的内录设备,设置回调接收音频数据 - 启动AudioQueue开始捕获音频
关键设备查询代码:
import AudioToolbox func getInternalCaptureDeviceID() -> AudioDeviceID? { var deviceID: AudioDeviceID = 0 var propertyAddr = AudioObjectPropertyAddress( mSelector: kAudioHardwarePropertyDefaultInputDevice, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster ) var propertySize = UInt32(MemoryLayout<AudioDeviceID>.size) let status = AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddr, 0, nil, &propertySize, &deviceID) return status == noErr ? deviceID : nil }
核心注意点
AVAudioRecord仅支持麦克风输入,无法实现内录,必须切换上述方案- 内录功能无需麦克风权限,若APP之前请求过麦克风权限,需确保内录流程不激活麦克风输入
- 部分旧款iOS设备可能不支持内录,需提前做兼容性判断
内容的提问来源于stack exchange,提问作者Daniel Tuck
相关产品推荐
相关产品推荐

