添加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
相关产品推荐
相关产品推荐

