visionOS平台AVCaptureAudioDataOutput替代方案及AVAudioBuffer获取咨询
visionOS 下获取 AVAudioBuffer 的可行思路
基于录制回调直接捕获
既然已确认音频录制功能可用,可通过AVAudioRecorder结合自定义逻辑捕获AVAudioBuffer。先配置好音频会话和录制格式,再借助底层回调或引擎tap获取缓冲区:let session = AVAudioSession.sharedInstance() do { try session.setCategory(.record, mode: .default) try session.setActive(true) let settings: [String: Any] = [ AVFormatIDKey: kAudioFormatLinearPCM, AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 1, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsFloatKey: false, AVLinearPCMIsBigEndianKey: false ] let recorder = try AVAudioRecorder(url: temporaryFileURL, settings: settings) recorder.prepareToRecord() // 后续可结合AudioQueue或AVAudioEngine的tap逻辑获取buffer } catch { print("配置失败: \(error)") }尝试AVAudioEngine输入节点Tap
尽管visionOS初期对AVAudioEngine支持有限,但输入节点tap是获取实时音频缓冲区的常规方案,可尝试如下实现:let engine = AVAudioEngine() let inputNode = engine.inputNode let inputFormat = inputNode.inputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: inputFormat) { (buffer: AVAudioPCMBuffer, time: AVAudioTime) in // 此处直接拿到AVAudioPCMBuffer,可直接处理 print("捕获缓冲区帧数: \(buffer.frameLength)") } do { try engine.start() } catch { print("引擎启动失败: \(error)") }注意:必须在Info.plist中添加
NSMicrophoneUsageDescription字段申请麦克风权限,否则会无响应或崩溃。底层Core Audio API兜底
如果高层API无法生效,可直接用Core Audio的AudioQueue录制并包装成AVAudioBuffer,兼容性更强:var audioFormat = AudioStreamBasicDescription() audioFormat.mSampleRate = 44100.0 audioFormat.mFormatID = kAudioFormatLinearPCM audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked audioFormat.mChannelsPerFrame = 1 audioFormat.mBitsPerChannel = 16 audioFormat.mBytesPerPacket = 2 audioFormat.mFramesPerPacket = 1 audioFormat.mBytesPerFrame = 2 func setupAudioQueue() { var queue: AudioQueueRef? AudioQueueNewInput(&audioFormat, audioQueueCallback, nil, nil, nil, 0, &queue) AudioQueueStart(queue!, nil) } func audioQueueCallback(queue: AudioQueueRef, buffer: AudioQueueBufferRef, startTime: UnsafePointer<AudioTimeStamp>, numPackets: UInt32, packetDescs: UnsafePointer<AudioStreamPacketDescription>?) { // 将AudioQueueBuffer数据拷贝到AVAudioPCMBuffer guard let pcmFormat = AVAudioFormat(streamDescription: &audioFormat) else { return } let pcmBuffer = AVAudioPCMBuffer(pcmFormat: pcmFormat, frameCapacity: AVAudioFrameCount(numPackets)) pcmBuffer?.frameLength = AVAudioFrameCount(numPackets) memcpy(pcmBuffer?.int16ChannelData?[0], buffer.pointee.mAudioData, Int(buffer.pointee.mAudioDataBytesCapacity)) // 处理pcmBuffer AudioQueueEnqueueBuffer(queue, buffer, 0, nil) }检查会话配置与权限
所有音频操作的前提是正确配置会话并获取权限:let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playAndRecord, options: .mixWithOthers) try session.setActive(true) let hasPermission = await session.requestRecordPermission() guard hasPermission else { print("未获取麦克风权限") return } } catch { print("会话配置失败: \(error)") }
内容的提问来源于stack exchange,提问作者Pietro Messineo
相关产品推荐
相关产品推荐

