文本转语音错误,与语音转文本按钮冲突 [英] Text to speech error, conflicting with the speech to text button

查看:51
本文介绍了文本转语音错误,与语音转文本按钮冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试同时使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆