文本转语音错误,与语音转文本按钮冲突 [英] Text to speech error, conflicting with the speech to text button
问题描述
我正在尝试同时使用 iOS 语音到文本 api 和文本到语音 api.基本上用户会说话,他们所说的内容将被转录到文本视图中.然后用户将按下一个按钮,该按钮将从文本视图中转录的文本提供文本到语音.我的错误是当用户按下语音转文本按钮时,文本转语音按钮停止工作.但是,如果我根本不按下语音转文本按钮并通过键盘在文本视图中输入一些文本,那么文本转语音按钮就起作用了.我猜是语音转文本按钮有问题.我的代码没有出现任何错误,我对发生的事情感到困惑.
I am trying to use iOS speech to text api and text to speech api together. Basically a user will speak and what they say will be transcribed in a textview. Then the user will press a button which will provide text to speech from the transcribed text in the textview. My error is that when the user presses the speech-to-text button, the text to speech button stops working. However if I don't press the speech to text button at all and input some text in the textview via keyboard then text to speech button works. I am guess it is has issue with the speech to text button. I am not getting any errors on my code and i am confused as to what is going on.
import UIKit
import Speech
import AVFoundation
class SpeechRecognitionViewController: UIViewController, SFSpeechRecognizerDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
private var speechRecognizer: SFSpeechRecognizer!
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest!
private var recognitionTask: SFSpeechRecognitionTask!
private let audioEngine = AVAudioEngine()
private var locales: [Locale]!
private let defaultLocale = Locale(identifier: "en-US")
@IBOutlet weak var recordBtn: UIButton!
@IBOutlet weak var speaker: UIButton!
@IBOutlet weak var textView: UITextField!
//@IBOutlet weak var textView: UITextView!
//@IBOutlet private weak var recordBtn : UIButton!
//@IBOutlet private weak var picker: UIPickerView!
@IBOutlet weak var picker: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
recordBtn.isEnabled = false
locales = SFSpeechRecognizer.supportedLocales().map({$0})
let index = NSArray(array: locales).index(of: defaultLocale)
picker.selectRow(index, inComponent: 0, animated: false)
prepareRecognizer(locale: defaultLocale)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
SFSpeechRecognizer.requestAuthorization { authStatus in
/*
The callback may not be called on the main thread. Add an
operation to the main queue to update the record button's state.
*/
OperationQueue.main.addOperation {
switch authStatus {
case .authorized:
self.recordBtn.isEnabled = true
case .denied:
self.recordBtn.isEnabled = false
self.recordBtn.setTitle("User denied access to speech recognition", for: .disabled)
case .restricted:
self.recordBtn.isEnabled = false
self.recordBtn.setTitle("Speech recognition restricted on this device", for: .disabled)
case .notDetermined:
self.recordBtn.isEnabled = false
self.recordBtn.setTitle("Speech recognition not yet authorized", for: .disabled)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
private func prepareRecognizer(locale: Locale) {
speechRecognizer = SFSpeechRecognizer(locale: locale)!
speechRecognizer.delegate = self
}
private func startRecording() throws {
// Cancel the previous task if it's running.
if let recognitionTask = recognitionTask {
recognitionTask.cancel()
self.recognitionTask = nil
}
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(AVAudioSessionCategoryRecord)
try audioSession.setMode(AVAudioSessionModeMeasurement)
try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") }
guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") }
// Configure request so that results are returned before audio recording is finished
recognitionRequest.shouldReportPartialResults = true
// A recognition task represents a speech recognition session.
// We keep a reference to the task so that it can be cancelled.
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
var isFinal = false
if let result = result {
self.textView.text = result.bestTranscription.formattedString
isFinal = result.isFinal
}
if error != nil || isFinal {
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
self.recordBtn.isEnabled = true
self.recordBtn.setTitle("Start Recording", for: [])
}
}
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
try audioEngine.start()
textView.text = "(listening...)"
}
// =========================================================================
// MARK: - UIPickerViewDataSource
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return locales.count
}
// =========================================================================
// MARK: - UIPickerViewDelegate
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return locales[row].identifier
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let locale = locales[row]
prepareRecognizer(locale: locale)
}
// =========================================================================
// MARK: - SFSpeechRecognizerDelegate
public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
if available {
recordBtn.isEnabled = true
recordBtn.setTitle("Start Recording", for: [])
} else {
recordBtn.isEnabled = false
recordBtn.setTitle("Recognition not available", for: .disabled)
}
}
// =========================================================================
// MARK: - Actions
@IBAction func recordbuttontapped(_ sender: Any) {
if audioEngine.isRunning {
audioEngine.stop()
recognitionRequest?.endAudio()
recordBtn.isEnabled = false
recordBtn.setTitle("Stopping", for: .disabled)
} else {
try! startRecording()
recordBtn.setTitle("Stop recording", for: [])
}
}
@IBAction func speaktome(_ sender: Any) {
let something = textView.text!
let utterance = AVSpeechUtterance(string: something)
utterance.voice = AVSpeechSynthesisVoice(language: "en-US" )
let synthesizer = AVSpeechSynthesizer()
synthesizer.speak(utterance)
}
}
推荐答案
更改试试audioSession.setCategory(AVAudioSessionCategoryRecord)
到 尝试 audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
它应该按预期工作.在语音到文本期间,您将音频会话更改为录制模式,并且在 TTS 期间不会更改为播放模式.另一种选择是在 TTS 期间将音频会话设置为 AVAudioSessionCategoryPlayback
.
Change the try audioSession.setCategory(AVAudioSessionCategoryRecord)
to try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
it should work as intended. During speech to text you are changing the audio session to record mode and it is not getting changed to play mode during TTS. The other alternative is to set the audio session to AVAudioSessionCategoryPlayback
during the TTS.
这篇关于文本转语音错误,与语音转文本按钮冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!