You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS平台SFSpeechRecognizer是否支持噪音消除及唤醒词识别优化

解决方案

针对APP播放音频时SFSpeechRecognizer捕获扬声器声音导致唤醒词失效的问题,可以尝试以下几种方案:

1. 启用系统内置回声消除(AEC)

iOS的AudioSession在特定模式下会自动启用回声消除功能,你当前使用的.spokenAudio模式虽适用于语音场景,但.voiceChat或.videoChat模式对回声消除的优化更针对性。调整AudioSession配置如下:

try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.duckOthers, .allowBluetoothA2DP, .defaultToSpeaker])
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)

添加.defaultToSpeaker选项可确保音频从扬声器输出,配合.voiceChat模式触发系统回声消除逻辑,有效抑制麦克风捕获的自播放音频。

2. 手动抵消播放的音频缓冲区

既然APP掌握要播放的音频数据,可在麦克风捕获的缓冲区中做相位抵消——用播放的原始音频数据反向叠加到麦克风输入上,抵消自播放声音:

  • 保存播放音频的PCM数据缓冲区(需与麦克风采样率、位深一致)
  • 在AVAudioEngine输入节点回调中,将捕获的缓冲区数据与播放缓冲区数据做减法运算(需处理时间同步,计算播放与捕获的延迟偏移)
  • 将处理后的缓冲区传给SFSpeechAudioBufferRecognitionRequest

示例代码片段:

// 假设playBuffer是保存的播放音频缓冲区
audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: inputFormat) { [weak self] buffer, time in
    guard let self = self, let playBuffer = self.playBuffer else { return }
    // 计算播放与捕获的延迟偏移,需根据实际场景调整
    let offset = self.calculatePlaybackOffset(currentTime: time)
    if offset + buffer.frameLength <= playBuffer.frameLength {
        let inputData = buffer.floatChannelData![0]
        let playData = playBuffer.floatChannelData![0]
        // 执行相位抵消,0.8为抵消系数,可根据效果调整
        for i in 0..<Int(buffer.frameLength) {
            inputData[i] -= playData[offset + i] * 0.8
        }
    }
    // 将处理后的缓冲区传给识别请求
    self.recognitionRequest?.append(buffer)
}

3. 前置音频降噪处理

在将麦克风输入传给SFSpeechRecognizer前,通过音频处理单元做降噪,过滤扬声器背景噪音:

  • 使用系统自带的AVAudioUnitNoiseReduction降噪单元,或第三方轻量降噪库
  • 将降噪单元接入AVAudioEngine处理链,处理后的音频再送入识别请求

示例代码:

let noiseReductionUnit = AVAudioUnitNoiseReduction()
noiseReductionUnit.bypass = false
// 调整降噪参数,0.8为降噪强度,可按需修改
noiseReductionUnit.parameters[AVAudioUnitNoiseReductionParameter.reduction] = 0.8

audioEngine.attach(noiseReductionUnit)
audioEngine.connect(audioEngine.inputNode, to: noiseReductionUnit, format: inputFormat)
audioEngine.connect(noiseReductionUnit, to: audioEngine.mainMixerNode, format: inputFormat)

// 从降噪单元获取处理后的音频,传给识别请求
noiseReductionUnit.outputNode.installTap(onBus: 0, bufferSize: 1024, format: inputFormat) { buffer, time in
    self.recognitionRequest?.append(buffer)
}

4. 优化唤醒词检测逻辑

如果以上方法仍有残留,可在识别结果层面做过滤:

  • 记录APP播放的文本内容,在SFSpeechRecognitionResult返回时,先排除与播放文本匹配的结果
  • 为唤醒词设置更高的置信度阈值,仅当置信度超过阈值时触发唤醒

内容的提问来源于stack exchange,提问作者D'Fontalland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:16:27