MacOS Swift Speech框架转写报错:Audio input timestamp overlaps or precedes
Audio input timestamp overlaps or precedes prior audio input报错 在Mac上使用Apple Speech框架的SpeechTranscriber及DictationTranscriber做语音转写时,运行30-60秒后常触发以下报错:
Audio input timestamp overlaps or precedes prior audio input
结合你怀疑问题出在inputNode.installTap()代码块的判断,以下是针对性的排查和解决方法:
核心排查方向:音频时间戳的连续性
Speech框架对输入音频的时间戳顺序要求极高,只要出现时间戳回退、重叠,就会触发该错误,重点检查installTap回调中的时间戳处理逻辑:
1. 直接使用系统提供的时间戳,禁止手动修改
不要自行计算或调整音频帧的时间戳,完全依赖AVAudioEngine传递的time参数即可。错误的时间戳偏移会直接导致框架校验失败,正确的tap回调写法示例:
inputNode.installTap(onBus: 0, bufferSize: 1024, format: inputFormat) { [weak self] buffer, time in guard let self = self, let recognizer = self.speechRecognizer else { return } // 直接复用原始buffer和time,避免内存拷贝时的错误(若需要拷贝也要保证时间戳一致) recognizer.append(buffer, withAudioTime: time) }
2. 重启音频引擎前必须清理旧Tap
如果存在音频引擎中断、重启的场景,一定要先移除旧的Tap再重新安装,否则残留的旧流会导致时间戳混乱:
// 重启前先清理 inputNode.removeTap(onBus: 0) do { try audioEngine.stop() try audioEngine.start() // 重新安装Tap inputNode.installTap(onBus: 0, bufferSize: 1024, format: inputFormat, block: yourTapBlock) } catch { print("音频引擎操作失败:\(error)") }
同时监听AVAudioSession.interruptionNotification,在中断结束后执行完整的引擎重启流程,不要直接恢复旧的音频流。
3. 调整BufferSize适配系统
过大或过小的BufferSize可能导致时间戳计算异常,建议使用系统自动适配的参数,或者设置为输入格式帧长度的整数倍:
// 让系统自动选择合适的BufferSize inputNode.installTap(onBus: 0, bufferSize: AVAudioNodeBufferSizeAutomatic, format: inputFormat, block: yourTapBlock)
4. 定期重置SpeechRecognizer实例
长时间运行后,SpeechRecognizer内部状态可能出现异常,尝试每运行一段时间(比如30分钟)就销毁旧实例并创建新的,同时重置音频Tap,避免累积的时间戳错误。
控制台日志辅助排查
如果日志中能看到具体的时间戳数值,对比相邻音频帧的sampleTime,如果出现后一帧时间戳小于前一帧的情况,说明音频输入设备可能存在硬件层面的时间戳问题,或者有其他进程抢占了音频资源导致流中断,此时可以尝试切换音频输入设备,或者关闭其他占用音频的程序。
内容的提问来源于stack exchange,提问作者Saamer

