AVAudioSession音频调光错误:停用已运行I / O的音频会话

时间:2015-08-06 22:09:34

标签: xcode swift audio avaudioplayer avaudiosession

我正在播放几种声音,每种声音都会使背景音频变暗。完成后,我恢复背景音频。每当其中一个音频文件播放时,背景会变暗(根据需要)。当最后一个音频完成播放时,恢复背景音频(也是期望的)。但是大约5秒后,它会抛出此错误并再次使音频变暗(不是我想要的,因为所有声音现在都已完成)。

  

错误:[0x19c9af310] AVAudioSession.mm:646: - [AVAudioSession   setActive:withOptions:error:]:取消激活具有的音频会话   运行I / O.在停用之前,应停止或暂停所有I / O.   音频会议。

据我所知,我正在停止并删除所有音频。

我在这里发现了一篇帖子:

iOS8 AVAudioSession setActive error

但解决方案对我不起作用。这是我的音频播放器课程。如果你可以告诉我什么可能,我会很感激。

import Foundation
import AVFoundation

private var _singleton:O_Audio? = O_Audio()
private var _avAudioPlayers:Array<AVAudioPlayer> = []

//Manages dimming and resuming background audio
class O_Audio:NSObject, AVAudioPlayerDelegate
{
    class var SINGLETON:O_Audio
    {
        if(_singleton == nil)
        {
            _singleton = O_Audio()
        }
        return _singleton!
    }

    class func dimBackgroundAudio()
    {
        AVAudioSession.sharedInstance().setActive(true, error: nil)
    }

    class func restoreBackgroundAudio()
    {
        AVAudioSession.sharedInstance().setActive(false, error: nil)
    }

    class func playSound(path:String)
    {
        var sound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(path, ofType: "m4a")!)
        var audioPlayer = AVAudioPlayer(contentsOfURL: sound, error: nil)
        _avAudioPlayers.append(audioPlayer)
        audioPlayer.delegate = O_Audio.SINGLETON
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    }

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool)
    {
        //this was from the 1 stack post I found but these
        //two lines do not solve my problem
        player.stop()
        player.prepareToPlay()

        var index:Int!
        for i in 0..._avAudioPlayers.count - 1
        {
            if(_avAudioPlayers[i] == player)
            {
                index = i
                break
            }
        }

        _avAudioPlayers.removeAtIndex(index)

        if(_avAudioPlayers.count == 0)
        {
            O_Audio.restoreBackgroundAudio()
        }
    }

    func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!)
    {
        println("error")
    }
}

重要更新

所以我发现我认为这是问题的一个粗略原因。我们的应用程序基于Cordova构建。所以我们有很多Safari(浏览器)调用。每当我们播放视频(通过Safari播放)时,就会发生此错误。似乎Safari在某种程度上使音频变暗并保持运行的I / O线程。

4 个答案:

答案 0 :(得分:1)

问题在于MPMoviePlayerController对象正在播放。事实上,任何AVPlayerItem都会导致这种情况。如果您正在播放电影,并尝试调暗音频,则会出现此错误。

目前,在iOS上播放的任何电影都有一个不可变的音轨(即使电影文件中没有音频)。这永远导致鸭子问题(它是源代码中的一个错误)。我尝试了很多解决方法,没有任何效果。我确定这是一个Xcode源错误。

答案 1 :(得分:0)

@Aggressor:您可以将音频类别更改为多路径,以便音频通过扬声器和耳机(如果已插入)同时播放。

通过这种方式,您将无法获得暗淡的音频。

答案 2 :(得分:0)

I have the same issue. You must call AVAudioSession.sharedInstance().setActive(true, error: nil); before AVAudioSession.sharedInstance().setActive(false, error: nil);

And they are appear in pairs.

答案 3 :(得分:0)

我有同样的问题。我的应用使用AVPlayer播放视频(无声音),并且在视频仍在播放时偶尔使用AVQueuePlayer播放简短语音。现在,如果我有音乐在后台播放(例如通过Spotify),则音乐在播放AVQueuePlayer时会回避,在结束后的一小段时间内不再进行引诱,然后再次回避。

我创建了一个示例应用程序来调试我的问题,发现我的AVAudioSession设置没有得到正确处理。最终对我有用的是:

在应用启动时,将AVAudioSession.CategoryOptions设置为.ambient,如下所示:

try AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers)

这将防止视频播放器中断音乐。

如果我播放/暂停AVQueuePlayer,请使用以下功能再次更改类别:

func setAudioSession(to category: Category, activate: Bool = true) {
        switch category {
        case .default:
            // .ambient and .mixWithOthers so silent video won't interrupt background music
            setCategory(.ambient, options: .mixWithOthers, activate: activate)
        case .voiceOver:
            // .playback with .duckOthers will duck the music momentarily while short lasting audio is output, spoken audio will be interrupted by setting . interruptSpokenAudioAndMixWithOthers
            setCategory(.playback, options: [.duckOthers, .interruptSpokenAudioAndMixWithOthers], activate: activate)
        case .standalone:
            // For standalone audio use .playback without options so it will interrupt other background music, if you don't want the sound to play while the phone is on mute use .ambient instead
            setCategory(.playback, activate: activate)
        }
    }
    
    private func setCategory(_ category: AVAudioSession.Category, options: AVAudioSession.CategoryOptions = [], activate: Bool) {
        let session = AVAudioSession.sharedInstance()
        // Only set if needed
        guard session.category != category || session.categoryOptions != options else { return }
        // To change category, first setActive(false) -> change -> setActive(true)
        try? AVAudioSession.sharedInstance().setActive(false)
        try? AVAudioSession.sharedInstance().setCategory(category, options: options)
        if activate {
            try? AVAudioSession.sharedInstance().setActive(true)
        }
    }

enum Category {
        case `default`, voiceOver, standalone
    }

从根本上说,就是开始音频语音

   @IBAction func playAudio(_ sender: UIButton) {
        self.setAudioSession(to: .voiceOver)
        audioPlayer.load(url: Bundle.main.url(forResource: "audio", withExtension: "mp3")!)
        audioPlayer.play()
    }

然后暂停(或在队列完成后):

@IBAction func pauseAudio(_ sender: UIButton) {
    audioPlayer.pause()
    self.setAudioSession(to: .default)
}

⚠️免责声明:请注意我是如何try?而不是do try catch阻止的,这是因为我仍然遇到Deactivating an audio session that has running I/O.错误。因此,如果我发现错误,它将不再激活正确的会话。它仍然不是理想的,因为它总是会输出错误,但至少现在闪避就像灵符一样。