47 lines
1.4 KiB
Swift
47 lines
1.4 KiB
Swift
import AVFoundation
|
|
|
|
final class SpeechService: NSObject {
|
|
static let shared = SpeechService()
|
|
static let speakingDidChangeNotification = Notification.Name("SpeechServiceSpeakingDidChange")
|
|
|
|
private let synthesizer = AVSpeechSynthesizer()
|
|
private(set) var speakingText: String?
|
|
|
|
override init() {
|
|
super.init()
|
|
synthesizer.delegate = self
|
|
}
|
|
|
|
func isSpeaking(_ text: String) -> Bool {
|
|
speakingText == text
|
|
}
|
|
|
|
func speak(_ text: String) {
|
|
if synthesizer.isSpeaking {
|
|
synthesizer.stopSpeaking(at: .immediate)
|
|
}
|
|
let utterance = AVSpeechUtterance(string: text)
|
|
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
|
|
utterance.rate = AVSpeechUtteranceDefaultSpeechRate * 0.9
|
|
speakingText = text
|
|
notifySpeakingChanged()
|
|
synthesizer.speak(utterance)
|
|
}
|
|
|
|
private func notifySpeakingChanged() {
|
|
NotificationCenter.default.post(name: Self.speakingDidChangeNotification, object: self)
|
|
}
|
|
}
|
|
|
|
extension SpeechService: AVSpeechSynthesizerDelegate {
|
|
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
|
|
speakingText = nil
|
|
notifySpeakingChanged()
|
|
}
|
|
|
|
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {
|
|
speakingText = nil
|
|
notifySpeakingChanged()
|
|
}
|
|
}
|