2014-02-19 57 views
6

我想要做的是讓我的應用程序使用AVSpeechSynthesizer說話時背景音頻應用程序正在播放音頻。在我的應用發言時,我希望後臺應用的音頻「變暗」,然後在我的應用完成發言後返回原始音量。如何一致地停止AVAudioSession後AVSpeechUtterance

在我AudioFeedback類,我初始化我設置了AVAudioSessions像這樣:

self.session = [AVAudioSession sharedInstance]; 
    NSError *error; 
    [self.session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDuckOthers error:&error]; 

每當我想講一個新的話語,我做到以下幾點。我遵循An issue with AVSpeechSynthesizer, Any workarounds?的建議,每次創建一個新的AVSpeechSynthesizer,以「確保」取消總是被接收(它似乎工作,我不知道爲什麼)。

- (AVSpeechUtterance *) utteranceWithString: (NSString *) string 
{ 
    AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:string]; 
    utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-ES"]; 
    [utterance setRate:(AVSpeechUtteranceDefaultSpeechRate+AVSpeechUtteranceMinimumSpeechRate)/2.0]; 
    return utterance; 
} 

- (void) sayString: (NSString *) string cancelPrevious: (BOOL) cancelPrevious 
{ 
    [self.session setActive:enabled error:nil]; 
    if (cancelPrevious) { 
     AVSpeechSynthesizer *oldSynthesizer = self.voice; 
     self.voice = nil; 
     [oldSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; 
     self.voice = [[AVSpeechSynthesizer alloc] init]; 
     self.voice.delegate = self; 
    } 

    // Keep track of the final utterance, we'll use this to determine whether or not we should stop the audio session 
    self.finalUtterance = [self utteranceWithString:string]; 
    [self.voice speakUtterance:self.finalUtterance]; 
} 

在我AVSpeechSynthesizer委託方法,我檢查,看看我是否應該停止音頻會話返回後臺音頻正常音量如果當前AVSpeechSynthesizer和當前AVSpeechUtterance匹配最後已知的合成器和話語。

-(void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance 
{ 
    NSError *error; 
    // Only stop the audio session if this is the last created synthesizer 
    if (synthesizer == self.voice && self.finalUtterance == utterance) { 
     if ([self.session setActive:enabled error:&error]]) { 
      NSLog(@"Stopped the audio session: Speech synthesizer still speaking %d", synthesizer.speaking); 
     } else { 
      NSLog(@"ERROR failed to stop the audio session: %@. Speech synthesizer still speaking %d", error, synthesizer.speaking); 
     } 
    } 
} 

我遇到的問題是,有時,音頻對話會停止,而不問題,而其他時候,音頻會議將無法停止,出現以下錯誤:

Error Domain=NSOSStatusErrorDomain Code=2003329396 "The operation couldn’t be completed. (OSStatus error 2003329396.)"

我不知道如何保證我可以停止AVAudioSession。只要我無法停止音頻會話,我一直試圖保持呼叫[[AVAudioSession sharedInstance] setActive:NO error:&error],但這似乎不起作用。任何幫助將不勝感激。謝謝!

+1

對於那些接下來的人,我已經聯繫了Apple技術支持,並且他們要求我提出有關該問題的錯誤。就解決方法而言,我已切換到使用「AVAudioSessionCategoryOptionMixWithOthers」而不是「AVAudioSessionCategoryOptionDuckOthers」。 ShadowDES似乎有一個有限的解決方法,這對我來說不是一種可能性,但可能適用於其他人。我沒有自己嘗試過。 – kross

回答

0

我有同樣的問題,我相信我找到了它的原因。對我而言,如果我說的這個短語太短,就會給出錯誤。如果它「足夠長」,就沒有錯誤。

我測試

NSString *phraseToSay = [NSString stringWithFormat:@"One Two Three Four Five"]; // Gives the error 
NSString *phraseToSay = [NSString stringWithFormat:@"One Two Three Four Five Six"]; // No error 

我發現唯一的解決辦法是讓phraseToSay更長。

+0

Ooo有趣。不幸的是,這對我來說不是一個有用的工作,因爲我的短語會長短不一,而且通常很長。感謝分享!希望這有助於他人。 – kross

1

我發現如果我在幾秒鐘內再次嘗試,它會工作。我正在使用此代碼。

-(void)configureAVAudioSession:(bool)active { 

    AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 

    if (deactivationAttempt < 3) { // This doesn't always work first time, but don't want to keep trying forever if it decides not to work ever. 

     NSError *activationError = nil; 
     success = [audioSession setActive:active error:&activationError]; 

     if (!success) { 
      NSLog(@"(de)activation ERROR"); 
      ++deactivationAttempt; 
      [self performSelector:@selector(configureAVAudioSession:) withObject:false afterDelay:2.0]; 
     } 
     else { // Success! 
      deactivationAttempt = 0; 
     } 
    } 
    else { // Failed, but reset the counter in case we have more luck next time 
     deactivationAttempt = 0; 
    } 
} 

從文檔:

Deactivating your session will fail if any associated audio objects (such as queues, converters, players or recorders) are currently running.

我想這需要一段時間的話語從隊列中被清除。

+0

當您試圖關閉音頻會話時,合成器可能還沒有完成發言。您可以使用協議。它無時無刻都適用於我。 –