Swift:尝试在Swift中将语音转换为iPhone的语音时,iPhone的音量很低

9

我正在尝试语音识别示例。如果我开始通过麦克风识别我的语音,然后尝试获取iPhone的识别文本的声音,它可以工作。但是,声音太低。你能指导我吗?

与此不同的是,如果我在简单的按钮动作中尝试使用AVSpeechUtterance代码,则音量正常。

之后,如果我使用startRecognise()方法,音量会变得太低。

我的代码

func startRecognise()
{
let audioSession = AVAudioSession.sharedInstance()  //2
    do
    {
        try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try audioSession.setMode(AVAudioSessionModeDefault)
        try audioSession.setMode(AVAudioSessionModeMeasurement)
        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
        try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    }
    catch
    {
        print("audioSession properties weren't set because of an error.")
    }
    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    guard let inputNode = audioEngine.inputNode else {
        fatalError("Audio engine has no input node")
    }
    guard let recognitionRequest = recognitionRequest else {
        fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
    }
    recognitionRequest.shouldReportPartialResults = true
    recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
        if result != nil
        {
            let lastword = result?.bestTranscription.formattedString.components(separatedBy: " ").last
            if lastword == "repeat" || lastword == "Repeat"{
                self.myUtterance2 = AVSpeechUtterance(string: "You have spoken repeat")
                self.myUtterance2.rate = 0.4
                self.myUtterance2.volume = 1.0
                self.myUtterance2.pitchMultiplier = 1.0
                self.synth1.speak(self.myUtterance2)
                // HERE VOICE IS TOO LOW. 
            }
        }
    })
    let recordingFormat = inputNode.outputFormat(forBus: 0)  //11
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
    self.recognitionRequest?.append(buffer)
    }
    audioEngine.prepare()
    do 
    {
        try audioEngine.start()
    } 
    catch 
    {
        print("audioEngine couldn't start because of an error.")
    }
}

我的按钮动作

func buttonAction()
{
   self.myUtterance2 = AVSpeechUtterance(string: "You are in button action")
   self.myUtterance2.rate = 0.4
   self.myUtterance2.volume = 1.0
   self.myUtterance2.pitchMultiplier = 1.0
   self.synth1.speak(self.myUtterance2)
   // Before going for startRecognise() method, 
   //I tried with buttonAction(), 
   //this time volume is normal. 
   //After startRecognise() method call, volume is too low in both methods.
}

AVAudioSessionCategoryOptionDefaultToSpeaker -- 添加此选项 - yoshiiiiiiii
2个回答

19
最终,我找到了解决方案。
func startRecognise()
{
let audioSession = AVAudioSession.sharedInstance()  //2
    do
    {
        try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try audioSession.setMode(AVAudioSessionModeDefault)
        //try audioSession.setMode(AVAudioSessionModeMeasurement)
        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
        try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    }
    catch
    {
        print("audioSession properties weren't set because of an error.")
    }

    ... 
}

当我注释掉这行代码try audioSession.setMode(AVAudioSessionModeMeasurement)后,音量恢复正常。


3

经过深入了解技术细节,发现overrideOutputAudioPort()会暂时更改当前音频路由。

func overrideOutputAudioPort(_ portOverride: AVAudioSession.PortOverride) throws

如果您的应用程序使用playAndRecord类别,使用AVAudioSession.PortOverride.speaker选项调用此方法将导致音频路由到内置扬声器麦克风,而不考虑其他设置。
此更改仅在当前路由更改或再次使用AVAudioSession.PortOverride.none选项调用此方法时保持有效。
try audioSession.setMode(AVAudioSessionModeDefault)

如果您希望永久启用此行为,应将类别的"defaultToSpeaker"选项设置为true,而不是每次都设置。设置此选项将始终路由到扬声器,而不是接收器,如果没有使用其他附件,如耳机。在Swift 5.x中,上述代码如下 -
let audioSession = AVAudioSession.sharedInstance()
do {
  try audioSession.setCategory(.playAndRecord)
  try audioSession.setMode(.default)
  try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
  try audioSession.overrideOutputAudioPort(.speaker)
} catch {
  debugPrint("Enable to start audio engine")
  return
}

通过将模式设置为 measurement,它负责最小化对输入和输出信号的系统提供的信号处理。
try audioSession.setMode(.measurement)

通过对此模式进行注释并使用默认模式,负责永久启用音频路由到内置扬声器和麦克风。

感谢@McDonal_11的回答。希望这能帮助理解技术细节。


谢谢您的详细信息。我之前不知道这个。 :) - McDonal_11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接