iOS基于AVAudioEngine实现录音无输入自动超时停止方案
实现AVAudioEngine无音频输入时自动停止录制
你当前的代码逻辑是从录制启动时开始计时5秒后强制停止,而非检测"无音频输入的持续时长",所以需要调整为「检测音频输入强度+重置计时」的逻辑,具体实现步骤如下:
1. 添加必要的属性
在你的类中新增两个属性,用于跟踪音频状态和计时:
// 记录最后一次检测到有效音频的时间 private var lastActiveAudioTime: DispatchTime? // 静音阈值(可根据需求调整,0.01对应-40dB左右) private let silenceThreshold: Float = 0.01
2. 实现音频音量计算方法
添加一个工具方法,用于计算音频缓冲区的音量(这里用RMS均方根音量,比峰值更稳定):
private func calculateVolume(from buffer: AVAudioPCMBuffer) -> Float { guard let channelData = buffer.floatChannelData else { return 0 } let channelCount = Int(buffer.format.channelCount) let frameLength = UInt(buffer.frameLength) var sum: Float = 0 for channel in 0..<channelCount { let data = channelData[channel] for i in 0..<Int(frameLength) { sum += data[i] * data[i] } } let rms = sqrt(sum / Float(frameLength * UInt(channelCount))) return rms }
3. 修改startRecording方法
调整录制逻辑,每次收到音频缓冲区时先判断是否有有效输入,再更新计时,最后检查超时:
func startRecording() throws { guard let engine = self.audioEngine, let mic = mic else { return } let micFormat = mic.inputFormat(forBus: 0) self.state = .recording // 初始化最后活跃音频时间为当前时间 self.lastActiveAudioTime = DispatchTime.now() mic.installTap(onBus: 0, bufferSize: 4096, format: micFormat) { [weak self] (buffer, when) in guard let self = self else { return } // 1. 计算当前缓冲区的音量 let volume = self.calculateVolume(from: buffer) // 2. 如果音量超过阈值,更新最后活跃时间 if volume > self.silenceThreshold { self.lastActiveAudioTime = DispatchTime.now() } // 3. 保存当前音频数据(你的原有逻辑) self.baseData = buffer.data().base64EncodedString() // 4. 检查是否超过无输入超时时间(5秒) guard let lastTime = self.lastActiveAudioTime else { return } let elapsedSinceLastActive = DispatchTime.now().uptimeNanoseconds - lastTime.uptimeNanoseconds let timeoutNanoseconds = 5 * 1_000_000_000 // 5秒转纳秒 if elapsedSinceLastActive > timeoutNanoseconds { // 回到主线程停止录制(避免音频线程操作UI/引擎的线程问题) DispatchQueue.main.async { self.stopRecording() } } } if engine.isRunning { return } try engine.start() }
关键说明
- 静音阈值调整:
silenceThreshold可以根据你的场景微调,比如环境噪音大的话可以设为0.05,安静环境设为0.005 - 线程安全:停止录制的操作必须切到主线程,因为AVAudioEngine的大部分API需要在主线程调用
- 缓冲区大小:当前用的4096帧,对应约93毫秒(44.1kHz采样率下),这个值会影响检测的灵敏度,越小越灵敏但计算量略高
内容的提问来源于stack exchange,提问作者Farhandika
相关产品推荐
相关产品推荐

