Search code examples
iosswift3xcode8text-to-speechavspeechsynthesizer

AVspeechSynthesizer iOS text speech


i am new to swift and iOS application development. I am creating a text to speech application using the AVSpeechSynthesiser. I am wanting to set a string say in English but i am wanting it to translate that particular string to speech but in a different language such as Arabic. Am I able to do this using the AVSpeechSynthesizer, or would i need to use a translation API to do this.

ThankYou


Solution

  • I threw together an AVSpeechSynthesizer class to handle flipping from one language to another. Here's a AVSpeechSynthesizer tutorial on NSHipster that's a good starting point for learning about this. I haven't fiddled with translation, but you can figure that part out...I also created a basic translator class that'll translate "hello" to "مرحبا". You can see the project here:

    TranslateDemo

    To use the translator, you'd probably want to tie an action to a button like so:

    @IBAction func translateToArabicAction(_ sender: UIButton) {
        // check that there are characters entered in the textField
        if (textToTranslateTextField.text?.characters.count)! > 0 {
            let translatedText = translator.translate(word: (textToTranslateTextField.text?.lowercased())!)
            speechSynthesizer.speak(translatedText, in: Language.arabic.rawValue)
        }
    }
    
    @IBAction func translateToEnglishAction(_ sender: UIButton) {
        // check that there are characters entered in the textField
        if (textToTranslateTextField.text?.characters.count)! > 0 {
            let translatedText = translator.translate(word: (textToTranslateTextField.text?.lowercased())!)
            speechSynthesizer.speak(translatedText, in: Language.english.rawValue)
        }
    }
    

    The speech synthesizer looks like this:

    import AVFoundation
    
    // You can use an enum so you don't have to manually type out character strings. Look them up once and stick them in an enum. From there, you set the language with your enum rather than typing out the string.
    enum Language: String {
        case english = "en-US"
        case arabic = "ar-SA"
    }
    
    class Speaker: NSObject {
    
        let synth = AVSpeechSynthesizer()
    
        override init() {
            super.init()
            synth.delegate = self
        }
    
        func speak(_ announcement: String, in language: String) {
            print("speak announcement in language \(language) called")
            prepareAudioSession()
            let utterance = AVSpeechUtterance(string: announcement.lowercased())
            utterance.voice = AVSpeechSynthesisVoice(language: language)
            synth.speak(utterance)
        }
    
        private func prepareAudioSession() {
            do {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, with: .mixWithOthers)
            } catch {
                print(error)
            }
    
            do {
                try AVAudioSession.sharedInstance().setActive(true)
            } catch {
                print(error)
            }
        }
    
        func stop() {
            if synth.isSpeaking {
                synth.stopSpeaking(at: .immediate)
            }
        }
    }
    
    extension Speaker: AVSpeechSynthesizerDelegate {
        func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
            print("Speaker class started")
        }
    
        func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
            print("Speaker class finished")
        }
    }