【问题标题】:AVAudioSession never stoppedAVAudioSession 从未停止
【发布时间】:2017-04-12 15:14:24
【问题描述】:

我正在尝试将我的 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 {}
           }
       }
    }
}

我的方法被正确调用,但是当utterance 完成时我的audioSession 仍然处于活动状态。我尝试了很多东西,但没有任何效果:(。

【问题讨论】:

  • 也许可以看看this post
  • @GCBenson 谢谢你的链接,但不能用它解决它:(
  • @Makaille 您如何检查audioSession 是否仍然处于活动状态?
  • @arunjos007 我不确定你的意思。你想知道我是如何知道我的音频会话仍然处于活动状态的吗?
  • @Makaille 是的,就是这样

标签: ios swift swift3 avaudiosession


【解决方案1】:

您无法停止或停用AudioSession,您的应用会在启动时获取它。 Documentation:

音频会话是您的应用和 iOS 之间的中介,用于配置应用的音频行为。启动后,您的应用会自动获得单例音频会话。

所以-setActive: 方法不会使您的AudioSession“活跃”,它只是将其类别和模式配置付诸实施。要回到“正常状态”,你可以设置default settings或者直接调用setActive(false, with:.notifyOthersOnDeactivation)就够了。

【讨论】:

  • 如您所见,这就是我正在做的事情,我正在尝试找出为什么结果除外的原因不存在。我打电话给setActive(false, with:.notifyOthersOnDeactivation),但它没有任何改变
  • 我说你做对了:) 你期望什么样的结果?方法setActive(false) 不应该改变它,它只是告诉系统媒体恶魔,你的应用程序不需要以前的音频设置。如果您想重置某些设置,您需要停用音频会话,将设置更改为默认设置,然后激活它。
  • 目前,我正在耳机上听来自 spotify 的音乐(例如),我的应用程序会说“你正在跑 10 公里......”。所以我的音乐的声音会很低,在谈话过程中。演讲结束后,来自 spotify 的音乐不会恢复到之前的音量。
  • 好吧。要中断背景声音然后恢复,您需要设置适当的类别(在您的情况下为AVAudioSessionCategoryPlayback),没有任何选项(默认为其他音频中断),激活AudioSession并在播放完毕后将其停用。
  • 我在这里挂机,因为我有类似的问题。实例化 AudioSession 确实会影响应用程序的其他部分。例如。如果之前实例化了 AudioSession,AVPlayer 将不会开始播放......我无法解决这个问题。
【解决方案2】:

来自documentation of AVAudioSession的一部分:

讨论

如果另一个活动音频会话的优先级高于您的优先级(对于 例如,一个电话),并且两个音频会话都不允许混合, 尝试激活您的音频会话失败。 停用您的 如果任何关联的音频对象(例如队列、 转换器、播放器或记录器)当前正在运行。

我的猜测是未能停用会话是您的 queue 正在运行的进程,正如我在文档引用中强调的那样。

您可能应该使停用过程同步而不是异步确保您的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 {}
           }
       }
    }

【讨论】:

  • 你好,我回来了,这不能更多地同步工作。我做了不同的测试,当我用蓝牙设备连接到音频时出现了错误的行为。
  • 暂时没问题,要测试一下,你能不能添加一个 10-15 秒的延迟,然后尝试停用声音,这可能是由于队列中有一些待处理的正在运行的操作而失败。
【解决方案3】:

我建议使用 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
        }

【讨论】:

  • 感谢您的回答,但我没有使用播放器和任何 wav 或其他声音文件。我通过字符串创建声音,这就是我使用语音合成器的原因
猜你喜欢
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 2014-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多