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

添加Speech to Text后Text to Speech音量异常降低技术求助

解决添加语音识别后文本转语音音量过低的问题

我之前也踩过这个坑!问题的核心在于**AVAudioEngine会修改系统的音频会话设置**,而且使用后没有正确恢复,导致后续的文本转语音(TTS)被强制压低音量。

当你启动语音识别时,AVAudioEngine会自动将音频会话类别切换为.record或.playAndRecord——这个模式是为了优先保障麦克风输入,会限制播放通道的音量。如果用完不重置,TTS就会一直处于这个受限的会话环境里,自然声音很小。

下面是具体的修复方案:

1. 完善语音识别的停止逻辑,重置音频会话

在你的SpeechToText类里,添加一个停止录音并恢复会话的方法,确保每次录音结束后把音频会话切回适合播放的状态:

func stopRecording() {
    // 停止音频引擎和识别任务
    audioEngine.stop()
    request.endAudio()
    recognitionTask?.cancel()
    recognitionTask = nil
    
    // 重置音频会话到播放模式
    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
        try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    } catch {
        print("重置音频会话失败: \(error)")
    }
}

然后修改你的录音按钮点击逻辑,支持切换启停状态:

@objc func speechToTextButtonTapped() {
    if audioEngine.isRunning {
        stopRecording()
        speechToTextButton.setTitle("开始录音", for: .normal)
    } else {
        recordAndConvertSpeech()
        speechToTextButton.setTitle("停止录音", for: .normal)
    }
}

2. 确保TTS播放前设置正确的音频会话

在TextToSpeech类里,每次播放前主动设置音频会话为.playback模式,避免其他操作干扰:

import UIKit
import AVFoundation

class TextToSpeech: NSObject, AVSpeechSynthesizerDelegate {
    private let synthesizer = AVSpeechSynthesizer()
    var rate: Float = AVSpeechUtteranceDefaultSpeechRate
    var voice = AVSpeechSynthesisVoice(language: "en-US")
    
    override init() {
        super.init()
        synthesizer.delegate = self
    }
    
    func say(_ phrase: String) {
        // 切换到播放专用的音频会话
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print("设置TTS音频会话失败: \(error)")
        }
        
        let utterance = AVSpeechUtterance(string: phrase)
        utterance.rate = rate
        utterance.voice = voice
        synthesizer.speak(utterance)
    }
    
    // 播放结束后去激活会话,避免占用资源
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        do {
            try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
        } catch {
            print("去激活音频会话失败: \(error)")
        }
    }
}

3. 小细节优化

  • 变量名遵循Swift小驼峰规范(比如把Rate改成rate,Utterance改成utterance),代码更易读。
  • 在TextToSpeechTest里,避免强制解包label.text,防止崩溃:
    override func viewDidLoad(){
        super.viewDidLoad()
        speak.say(label.text ?? "默认文本")
    }
    

做完这些修改后,TTS的音量应该就能恢复到正常水平了——本质就是让录音和播放各自使用适合的音频会话,避免互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:07:50