Created
April 23, 2022 21:56
-
-
Save bubudrc/9607875bc53af9bb7f6c69ec7d05fd06 to your computer and use it in GitHub Desktop.
This a singleton class that lets dev start, pause, stop an speech in a correct way. Because is a singleton, you can share the instance throw the app. Also, because we set an AVAudioSession, we are able to keep listening the audio when the app goes to the background. To work correctly, you must to set the Capability 'Audio, AirPlay, and Picture i…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SpeechManager.swift | |
// | |
// Created by Marcelo Perretta on 22/04/2022. | |
// | |
import Foundation | |
import AVFoundation | |
// We need this because the delegate doesnt works correctly | |
enum SpeechState { | |
case reading, paused, stopped | |
} | |
final class SpeechManager { | |
private let synthesizer: AVSpeechSynthesizer = AVSpeechSynthesizer() | |
private let audioSession = AVAudioSession.sharedInstance() | |
private var speechState: SpeechState = .stopped | |
var utterance: AVSpeechUtterance? | |
// init() { | |
// synthesizer.usesApplicationAudioSession = true | |
// } | |
static var shared = SpeechManager() | |
deinit { | |
speechState = .stopped | |
do { | |
try audioSession.setActive(false, options: .notifyOthersOnDeactivation) | |
} catch { | |
print("audioSession properties weren't disable.") | |
} | |
} | |
func playContent(_ content: String, withLanguge language: String?) { | |
utterance = AVSpeechUtterance(string: content) | |
if let language = language { | |
utterance?.voice = AVSpeechSynthesisVoice(language: language) | |
} | |
guard let utterance = utterance else { return } | |
playContent(utterance) | |
} | |
func playContent(_ content: AVSpeechUtterance) { | |
if synthesizer.isSpeaking { | |
synthesizer.stopSpeaking(at: .immediate) | |
} | |
// This script let us to keep playing the audio speech on background | |
do { | |
try audioSession.setCategory( | |
AVAudioSession.Category.playback, | |
options: AVAudioSession.CategoryOptions.duckOthers | |
) | |
} catch { | |
print("ERRR CREATING AUDIO SESSION: \(error)") | |
} | |
synthesizer.speak(content) | |
speechState = .reading | |
} | |
func pauseContent() { | |
guard speechState == .reading else { return } | |
synthesizer.pauseSpeaking(at: .immediate) | |
speechState = .paused | |
} | |
func resumeContent() { | |
guard speechState == .paused else { return } | |
synthesizer.continueSpeaking() | |
speechState = .reading | |
} | |
func stopContent() { | |
synthesizer.stopSpeaking(at: .immediate) | |
utterance = nil | |
speechState = .stopped | |
} | |
func toggleContent() { | |
if speechState == .reading { | |
pauseContent() | |
} else if speechState == .paused { | |
resumeContent() | |
} else { | |
assertionFailure("NEEDS CREATE A CONTENT") | |
stopContent() | |
guard let utterance = utterance else { return } | |
playContent(utterance) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment