7

I'm using AVSpeechSynthesizer in a singleton. In iOS 8, when the app gets backgrounded for a while, when it resumes the AVSpeechSynthesizer singleton will no longer speak. This issue does not happen on iOS 7.

When the app gets backgrounded, the following message shows up in my log:

AVSpeechSynthesizer Audio interruption notification: {
    AVAudioSessionInterruptionTypeKey = 1;
}

I initialize the AVSpeechSynthesizer like this in the singleton's init method:

    self.speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
    self.speechSynthesizer.delegate = self;

and I speak the utterance like this:

AVSpeechUtterance *utt = [[AVSpeechUtterance alloc] initWithString:dialogue];
utt.voice = [AVSpeechSynthesisVoice voiceWithLanguage:voice];

utt.pitchMultiplier = pitch;
utt.rate = rate;
utt.preUtteranceDelay = preDelay;
utt.postUtteranceDelay = postDelay;
utt.volume = volumeSetting;

[self.speechSynthesizer speakUtterance:utt];

Has anyone seen anything like this on iOS 8?

Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
bmueller
  • 2,681
  • 1
  • 27
  • 45

3 Answers3

13

I spent entire day chasing this insanity and I think I have found solution. My issue was that AVSpeechSynthesizer would work fine in foreground and background with ducking other audio right until the moment a phone call happens.

At that moment, speaking would stop working silently, without any errors. All the objects are still there but delegate calls would not get called, neither start nor finish.

I noticed that with phone calls, my app would get notification about AudioRouteChanged. Thus when that happens, I would re-create the speech setup: basically destroy existing AVSpeechSynthesizer and re-create it again. From then on, speaking will continue working. It would even work during the phone call :)

Aleksandar Vacić
  • 4,433
  • 35
  • 35
  • Yep, this works! Thanks for taking the time to get this sorted. Oh, and the correct notification name is `AVAudioSessionRouteChangeNotification` for anyone getting this in the future. – bmueller Feb 27 '15 at 17:14
  • Does this hack still work? I have the same scenario but in my case this doesn't work. iOS8.3/Xcode 6.3.2. I'am using AVAudioSessionCategoryPlayback + AVAudioSessionCategoryOptionDuckOthers – Ivan Jun 26 '15 at 21:52
  • I had to use: var err: NSError? = nil AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: &err) – BaseZen Jul 27 '15 at 02:48
  • It still works. iOS9.1. This saved me lots of time. Thank you. – Billy Nov 17 '15 at 01:35
  • Wow thanks! What I did was re-creating the AVSpeechSynthesizer each time there was no active speech speaking (isSpeaking) – Sjoerd Perfors Jan 08 '16 at 17:07
  • 2
    Could you post the correct code to solve this?? I have the same issue and I only get works this sometimes.. Thanks!! – user3745888 Feb 28 '17 at 20:41
  • Yes please can someone post the related code, I am having the exact same issue, that would be so useful... Thanks a lot ! – michael-martinez Oct 03 '19 at 15:37
2
  1. You must set "Audio and AirPlay" in background modes.
  2. You have to configure the audio session in your AppDelegate:

    NSError *error = NULL;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:&error];
    if(error) {
        // Do some error handling
    }
    [session setActive:YES error:&error];
    if (error) {
        // Do some error handling
    }
    

(See this post: https://stackoverflow.com/a/19200177/330067)

Community
  • 1
  • 1
Lukasz Czerwinski
  • 13,499
  • 10
  • 55
  • 65
0

After investigating further, it seems like AVSpeechSynthesizer is breaking when the app is launched in the background (due to background fetch or whatever). A simple call to check whether the app is currently active before speaking solves the problem.

if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
    [self.speechSynthesizer speakUtterance:utt];
bmueller
  • 2,681
  • 1
  • 27
  • 45
  • But using this, you basically prevent the speaking working in background, which is not ideal, especially for fitness apps. AVSpeechSynth works in background just fine until the phone call, after which AVSpeechSynth delegate calls do not happen nor the speaking is done at all. – Aleksandar Vacić Feb 26 '15 at 13:39