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

如何让iOS Speech框架区分用户真实语音与播放的MP3音频?

解决方案:过滤播放音频,让Speech框架只识别用户真实语音

要解决播放MP3时被误识别的问题,核心是让iOS系统的音频栈自动过滤掉扬声器输出的声音,同时引导Speech识别器专注于用户的语音输入。苹果备忘录的听写功能正是利用了系统内置的音频处理和识别优化,以下是具体实现方案:

1. 配置正确的AVAudioSession

首先必须设置合适的音频会话类别和模式,启用系统的回声消除(AEC)和自动增益控制(AGC),这样麦克风会自动忽略扬声器播放的声音:

private func configureAudioSession() throws {
    let session = AVAudioSession.sharedInstance()
    // 设置类别为同时播放和录音,适配语音通话场景的音频处理
    try session.setCategory(.playAndRecord, mode: .voiceChat, options: [.defaultToSpeaker, .allowBluetooth])
    // 激活会话并通知其他应用音频状态变化
    try session.setActive(true, options: .notifyOthersOnDeactivation)
}

2. 优化Speech识别请求的配置

给SFSpeechRecognitionRequest设置任务提示为听写,让识别器更聚焦于用户的实时语音输入,减少对播放音频的误识别:

recognitionRequest?.taskHint = .dictation
// 听写场景建议开启部分结果返回,提升交互体验
recognitionRequest?.shouldReportPartialResults = true

3. 修改启动代码,整合上述配置

把音频会话配置和识别请求优化加入到你的start()方法中,完整代码如下:

private var speechRecognizer: SFSpeechRecognizer?
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
private var audioEngine: AVAudioEngine?

func start() {
    // 先配置音频会话,这是过滤播放音频的关键
    do {
        try configureAudioSession()
    } catch {
        print("音频会话配置失败: \(error.localizedDescription)")
        return
    }

    self.speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))
    guard let speechRecognizer = speechRecognizer, speechRecognizer.isAvailable else {
        print("当前区域不支持日语语音识别")
        return
    }

    self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    guard let recognitionRequest = recognitionRequest else {
        print("无法创建语音识别请求")
        return
    }
    // 指定任务类型为听写,引导识别器聚焦用户实时语音
    recognitionRequest.taskHint = .dictation
    recognitionRequest.shouldReportPartialResults = true

    self.audioEngine = AVAudioEngine()
    guard let audioEngine = audioEngine, let inputNode = audioEngine.inputNode else {
        print("无法获取音频引擎输入节点")
        return
    }

    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
        recognitionRequest.append(buffer)
    }

    audioEngine.prepare()
    do {
        try audioEngine.start()
    } catch {
        print("音频引擎启动失败: \(error.localizedDescription)")
    }
}

private func configureAudioSession() throws {
    let session = AVAudioSession.sharedInstance()
    try session.setCategory(.playAndRecord, mode: .voiceChat, options: [.defaultToSpeaker, .allowBluetooth])
    try session.setActive(true, options: .notifyOthersOnDeactivation)
}

关键原理说明

  • .playAndRecord类别配合.voiceChat模式会自动启用系统的回声消除算法,这是过滤扬声器播放声音的核心逻辑。
  • taskHint = .dictation告诉Speech识别器当前场景是用户实时听写,会优先处理清晰的近距离语音,过滤背景或播放的音频。
  • 必须确保音频会话在音频引擎启动前激活,否则系统的音频优化处理不会生效。

内容的提问来源于stack exchange,提问作者Toru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:54:26