2017-04-12 11 views
2

我試圖將我的AVAudioSession設置爲非活動狀態以恢復到正常狀態。AVAudioSession從不停止

我的話語功能:

class SSpeech : NSObject, AVSpeechSynthesizerDelegate { 

    var group = DispatchGroup(); 
    var queue = DispatchQueue(label: "co.xxxx.speech", attributes: []) 

    class var sharedInstance: SSpeech { 
     struct Static { 
      static var instance: SSpeech? 
     } 
     if !(Static.instance != nil) { 
      Static.instance = SSpeech() 
     } 
     return Static.instance! 
    } 

    required override init() { 
     super.init(); 
     self.speechsynt.delegate = self; 
    } 

    deinit { 
     print("deinit SSpeech") 
    } 

    let audioSession = AVAudioSession.sharedInstance(); 
    var speechsynt: AVSpeechSynthesizer = AVSpeechSynthesizer() 
    var queueTalks = SQueue<String>(); 

    func pause() { 
     speechsynt.pauseSpeaking(at: .word) 
    } 

    func talk(_ sentence: String, languageCode code:String = SUtils.selectedLanguage.code, withEndPausing: Bool = false) { 
     if SUser.sharedInstance.currentUser.value!.speechOn != 1 { 
      return 
     } 

     queue.async{    
      self.queueTalks.enQueue(sentence) 
      do { 
       let category = AVAudioSessionCategoryPlayback; 
       var categoryOptions = AVAudioSessionCategoryOptions.duckOthers 
       if #available(iOS 9.0, *) { 
        categoryOptions.formUnion(AVAudioSessionCategoryOptions.interruptSpokenAudioAndMixWithOthers) 
       } 
       try self.audioSession.setCategory(category, with: categoryOptions) 
       try self.audioSession.setActive(true); 
      } catch _ { 
       return; 
      } 

      self.utteranceTalk(sentence, initSentence: false, speechsynt: self.speechsynt, languageCode:code, withEndPausing: withEndPausing) 

      do { 
       try self.audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.mixWithOthers) 
      } catch _ { 
       return; 
      } 
     } 
    } 

    func utteranceTalk(_ sentence: String, initSentence: Bool, speechsynt: AVSpeechSynthesizer, languageCode:String = "en-US", withEndPausing: Bool = false){ 
     if SUser.sharedInstance.currentUser.value!.speechOn != 1 { 
      return 
     } 

     let nextSpeech:AVSpeechUtterance = AVSpeechUtterance(string: sentence) 
     nextSpeech.voice = AVSpeechSynthesisVoice(language: languageCode) 
     if !initSentence { 
      nextSpeech.rate = 0.4; 
     } 

     if(withEndPausing){ 
      nextSpeech.postUtteranceDelay = 0.2; 
     } 
     speechsynt.speak(nextSpeech) 
    } 


    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance:AVSpeechUtterance) { 
     print("Speaker has finished to talk") 

     queue.async { 
       do { 
        try self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation) 
       } 
       catch {} 
      } 
     } 
    } 
} 

我的方法是正確調用,但我audioSessionutterance結束後仍然有效。我試過很多東西,但沒有工作:(中。

+0

也許看看[此帖](http://stackoverflow.com/questions/21893007/how-to-consistently-stop-avaudiosession-after-avspeechutterance ?rq = 1) – GCBenson

+0

@GCBenson感謝您的鏈接,但無法解決它:( – Makaille

+0

@Makaille你是如何檢查'audioSession'仍然活躍? – arunjos007

回答

0

我會建議使用AvAudioPlayer。他們非常容易啓動和停止命令。

首先聲明音頻播放器作爲一個變量

var SoundEffect: AVAudioPlayer! 

然後選擇文件,你需要

let path = Bundle.main.path(forResource: "Untitled2.wav", ofType:nil)! 
        let url = URL(fileURLWithPath: path) 
    let sound = try AVAudioPlayer(contentsOf: url) 
         SoundEffect = sound 
         sound.numberOfLoops = -1 
         sound.play() 

,並停止音頻播放器

if SoundEffect != nil { 
      SoundEffect.stop() 
      SoundEffect = nil 
     } 
+0

謝謝你的回答,但我沒有使用播放器和任何wav或其他聲音文件。我通過String創建聲音,這就是爲什麼我使用speechSynthetizer的原因 – Makaille

0

您無法停止或停用AudioSession,您的應用程序會在啓動時獲取它。 Documentation

音頻會話是您的應用和iOS之間的中介,用於配置應用的音頻行爲。發佈後,您的應用會自動獲取單一音頻會話。

所以方法-setActive:不會使你的AudioSession「活躍」,它只是把它的類別和模式配置付諸行動。爲了回到「正常狀態」,您可以設置default settings或者只需撥打setActive(false, with:.notifyOthersOnDeactivation),這就足夠了。

+0

正如你所看到的那樣,我正在做的事情,我試圖找到爲什麼除了結果不存在。我打電話給'setActive(false,with:.notifyOthersOnDeactivation)',但它沒有任何變化 – Makaille

+0

我說你做對了:)你期待什麼樣的結果? 'setActive(false)'方法不應該改變水平,它只是對系統媒體惡魔說,你的應用程序不需要以前的音頻設置。如果您想重置某些設置,您需要停用音頻會話,請將設置更改爲默認設置,將其激活。 – Asya

+0

目前,我正在用耳機播放spotify音樂(例如),我的應用程序會說「你正在跑10公里......」。所以在談話中,我的音樂聲很低。演講結束後,來自spotify的音樂不會回到他以前的音量。 – Makaille

0

的一部分從documentation of AVAudioSession

討論

如果另一個活動的音頻會話具有比你的更高的優先級(對於 例如,電話呼叫),和既不音頻會話允許混合, 試圖激活您的音頻會話失敗。 如果任何關聯的音頻對象(如隊列, 轉換器,播放器或錄音機)當前正在運行,那麼取消激活您的 會話將失敗。

我的猜測是,未能停用該會話是你queue運行過程中(ES)我在報價文件突出。

也許你應該停用過程異步同步代替 OR 確保所有在你queue正在運行的操作已被處理

這給一試:

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance:AVSpeechUtterance) { 
     print("Speaker has finished to talk") 

     queue.sync { // <---- `async` changed to `sync` 
       do { 
        try self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation) 
       } 
       catch {} 
      } 
     } 
    } 
+0

你好,我回來了,這不工作更多的同步。我已經完成了不同的測試,當我用bluethoot設備連接到音頻時,會出現不好的分量。 – Makaille

+0

好吧,暫時和測試,你可以添加一個說10-15秒的延遲,然後嘗試停用聲音,它可能會失敗,因爲隊列中的一些掛起的運行操作。 – NeverHopeless