AVSpeechSynthesizer检测语音何时结束

时间:2016-05-31 06:16:03

标签: ios swift avspeechsynthesizer

我只是不知道该怎么做......

我在这里和谷歌搜索,人们谈到了AVSpeechSynthesizerDelegate,但我无法使用它。

我想在演讲结束时准确地运行一个函数。

我怎样才能做到这一点?如果我必须使用代表,我应该怎么做?

我试过这样的方式:

func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) {
    falando = false
    print("FINISHED")
}

这是我在开发人员的文档中找到的功能之一,虽然演讲被告知并且没有打印出来。

我试图把A类:AVSpeechSynthesizerDelegate放进去,然后我会做Speech.delegate = self(Speech是AVSpeechSynthesizer类型的A属性),但是它说A不符合协议NSObjectProtocol。

一旦演讲结束,我怎么能运行一些功能(甚至是印刷品)?

谢谢!

4 个答案:

答案 0 :(得分:15)

A does not conform to protocol NSObjectProtocol表示您的类必须从NSObject继承,您可以阅读更多相关信息here

现在我不知道你的代码是如何构建的,但是这个小例子似乎对我有用。首先是一个包含AVSpeechSynthesizer

的简单类
class Speaker: NSObject {
    let synth = AVSpeechSynthesizer()

    override init() {
        super.init()
        synth.delegate = self
    }

    func speak(string: String) {
        let utterance = AVSpeechUtterance(string: string)
        synth.speakUtterance(utterance)
    }
}

请注意,我在这里设置了委托(在init方法中)并注意它必须从NSObject继承以保持编译器满意(非常重要!)

然后是实际的委托方法:

extension Speaker: AVSpeechSynthesizerDelegate {
    func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) {
        print("all done")
    }
}

最后,我可以在这里使用那个类,如下:

class ViewController: UIViewController {
    let speaker = Speaker()

    @IBAction func buttonTapped(sender: UIButton) {
        speaker.speak("Hello world")
    }
}

哪个奖励我

  

全部完成

AVSpeechSynthesizer停止说话时,在我的控制台中

希望对你有所帮助。

更新

所以,时间过去了,@ case-silva在下面的评论中询问是否有一个实际的例子,@ dima-gershman建议直接在AVSpeectSynthesizer中使用ViewController

为了适应这两种情况,我在此处制作了一个简单的ViewController示例UITextFieldUIButton

流程是:

  1. 您在文本字段中输入了一些文本(如果没有,则会设置默认值)
  2. 按下按钮
  3. 该按钮已被禁用且背景颜色已更改(对不起,这是我能想到的最佳效果:))
  4. 语音完成后,按钮启用,文本字段被清除,背景颜色再次更改。
  5. 以下是它的外观

    一个简单的UIViewController示例

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
    
        //MARK: Outlets
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var speakButton: UIButton!
    
        let synth = AVSpeechSynthesizer()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            synth.delegate = self
        }
    
        @IBAction func speakButtonTapped(_ sender: UIButton) {
            //We're ready to start speaking, disable UI while we're speaking
            view.backgroundColor = .darkGray
            speakButton.isEnabled = false
            let inputText = textField.text ?? ""
            let textToSpeak = inputText.isEmpty ? "Please enter some text" : inputText
    
            let speakUtterance = AVSpeechUtterance(string: textToSpeak)
            synth.speak(speakUtterance)
        }
    }
    
    extension ViewController: AVSpeechSynthesizerDelegate {
        func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
            //Speaking is done, enable speech UI for next round
            speakButton.isEnabled = true
            view.backgroundColor = .lightGray
            textField.text = ""
        }
    }
    

    希望能给你一个线索案例。

答案 1 :(得分:1)

函数viewDidAppear仅作为示例,可以根据需要将相同的代码放置在任何位置:

class MyViewController: UIViewController, AVSpeechSynthesizerDelegate {

    var synth = AVSpeechSynthesizer()

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // make sure to set the delegate before "speaking"
        synth.delegate = self

        let utterance = AVSpeechUtterance(string: "Hello world!")
        synth.speak(utterance)
    }

    // will be called when speech did finish
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        // do something useful here ...
    }
}

答案 2 :(得分:1)

SwiftUI

创建一个继承自 NSObjectObservableObjectSpeaker 类。

internal class Speaker: NSObject, ObservableObject {
    internal var errorDescription: String? = nil
    private let synthesizer: AVSpeechSynthesizer = AVSpeechSynthesizer()
    @Published var isSpeaking: Bool = false
    @Published var isShowingSpeakingErrorAlert: Bool = false

    override init() {
        super.init()
        self.synthesizer.delegate = self
    }

    internal func speak(_ text: String, language: String) {
        do {
            let utterance = AVSpeechUtterance(string: text)
            utterance.voice = AVSpeechSynthesisVoice(language: language)
            
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
            try AVAudioSession.sharedInstance().setActive(true)
            self.synthesizer.speak(utterance)
        } catch let error {
            self.errorDescription = error.localizedDescription
            isShowingSpeakingErrorAlert.toggle()
        }
    }
    
    internal func stop() {
        self.synthesizer.stopSpeaking(at: .immediate)
    }
}

扩展它并实现必要的委托方法。

extension Speaker: AVSpeechSynthesizerDelegate {
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
        self.isSpeaking = true
    }
    
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {
        self.isSpeaking = false
        try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    }
    
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        self.isSpeaking = false
        try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    }
}

使用 StateObject 包装器将 Speaker 添加到必要的视图中。

struct ContentView: View {
    let text: String = "Hello World!"
    @StateObject var speaker: Speaker = Speaker()
    
    var body: some View {
        HStack {
            Text(text)
            Spacer()
            Button(action: {
                if self.speaker.isSpeaking {
                    speaker.stop()
                } else {
                    speaker.speak(text, language: "en-US")
                }
            }) {
                Image(systemName: self.speaker.isSpeaking ? "stop.circle" : "speaker.wave.2.circle")
                    .resizable()
                    .frame(width: 30, height: 30)
            }
            .buttonStyle(BorderlessButtonStyle())
            .alert(isPresented: $speaker.isShowingSpeakingErrorAlert) {
                Alert(title: Text("Pronunciation error", comment: "Pronunciation error alert title."), message: Text(speaker.errorDescription ?? ""))
            }
        }
        .padding()
    }
}

答案 3 :(得分:0)

// import AVFoundation
import AVFoundation
// Adhere to AVSpeechSynthesizerDelegate
class GetDirectionsViewController: UIViewController, AVSpeechSynthesizerDelegate {
// define a speech session
let speechsynthesizer = AVSpeechSynthesizer()
// set the delegate
speechsynthesizer.delegate = self
// Implement didFinish. 
// This is called when speechsynthesizer completes speech
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        print("Speech finished")
    }
// Done!