使用 AVAudioPlayer 播放多个音频文件

Posted

技术标签:

【中文标题】使用 AVAudioPlayer 播放多个音频文件【英文标题】:Playing multiple audio files using AVAudioPlayer 【发布时间】:2017-02-19 06:50:08 【问题描述】:

我在 Main StoryBoard 上创建了 3 个 UIButton。

当我按下“Button1”或“Button2”时,每个都会播放一个音频文件(“player 1”,“player 2”。),当音频播放时,UIButton 设置为selected

我想让“Button3”连续实现多个功能。 这意味着当我按下“按钮 3”时,应该首先播放“玩家 3”,然后是“玩家 1”,然后是“玩家 2”。

但是,当我按下“Button3”时,“player 1”和“player 2”同时播放,因为前一个完成没有延迟。

我发现设置 AVAudioPlayer 的委托或使用 AVQueuePlayer 可以解决问题,但我发现很难进行更改。

    fileprivate var player1:AVAudioPlayer?
    fileprivate var player2:AVAudioPlayer?
    fileprivate var player3:AVAudioPlayer?


    @IBAction func pushButton1(sender: UIButton) 
        audioPlayer1(url: url1)
    

    @IBAction func pushButton2(sender: UIButton) 
        audioPlayer2(url: url2)
    

    @IBAction func pushButton3(_ sender: UIButton) 
        audioPlayer3(url: url1, url2: url2, url3: url3)
    


    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) 
        if (player === player1) 
            yourButton1.isSelected = false
         else if (player === player2) 
            yourButton2.isSelected = false
         else if (player === player3) 

            //"player 1" and "player 2" are played at same time

            yourButton3.isSelected = false
            player1!.play()
            yourButton1.isSelected = true
            player2!.play()
            yourButton2.isSelected = false
        
    


    func audioPlayer1(url: URL) 
        do 
            try player1 = AVAudioPlayer(contentsOf:url)
            player1!.play()
            yourButton1.isSelected = true
            player1!.delegate = self
         catch 
            print(error)
        
    

    func audioPlayer2(url: URL) 
        do 
            try player2 = AVAudioPlayer(contentsOf:url)
            player2!.play()
            yourButton2.isSelected = true
            player2!.delegate = self

         catch 
            print(error)
        
    

    func audioPlayer3(url: URL, url2: URL, url3: URL) 
        do 
            try player3 = AVAudioPlayer(contentsOf:url3)
            try player1 = AVAudioPlayer(contentsOf: url1)
            try player2 = AVAudioPlayer(contentsOf: url2)
            player3!.play()
            yourButton3.isSelected = true
            player3!.delegate = self
            player1!.delegate = self
         catch 
            print(error)
        
    

更改代码

    var queue = AVQueuePlayer()
    var items = [AVPlayerItem]()


    override func viewDidLoad() 
        super.viewDidLoad()
        player1?.delegate = self
        player2?.delegate = self
        player3?.delegate = self

        let asset1 = AVPlayerItem(url: url1)
        let asset2 = AVPlayerItem(url: url2)
        let asset3 = AVPlayerItem(url: url3)
        let asset4 = AVPlayerItem(url: url4)

        items = [asset1, asset2, asset3, asset4]

        queue = AVQueuePlayer(items: items)
        for item in queue.items() 
            NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(notification:)), name: .AVPlayerItemDidPlayToEndTime, object: item)
        

    
 @IBAction func pushButton3(_ sender: UIButton) 
        //audioPlayer3(url: url1, url2: url2)
        sender.isSelected = true
        queue.play()
    
 func playerItemDidReachEnd(notification: NSNotification) 

        if notification.object as? AVPlayerItem == items[0] 
            yourButton3.isSelected = false
            yourButton1.isSelected = true
        

        if notification.object as? AVPlayerItem == items[1] 
            yourButton1.isSelected = false
            yourButton2.isSelected = true
        

        if notification.object as? AVPlayerItem == items[2] 
            yourButton2.isSelected = false
            yourButton4.isSelected = true
            //yourButton1.isSelected = true
        

        if notification.object as? AVPlayerItem == items[3] 
            yourButton4.isSelected = false
            print("item 3")
        

【问题讨论】:

检查这个答案你会得到更好的主意:***.com/a/42273177/4033273 @MoinShirazi 使用 AppDelegate 不能用于此类事情,它违反了最佳实践。 【参考方案1】:

编辑:This is the method 用于 AVAudioPlayer

所以基本上:

1:只添加一个玩家,移除其余玩家。

2: Create an NSMutableArray 与您想玩的对象。

3:根据按下的按钮,您可以重新排列NSMutableArray 对象以根据需要设置正确的顺序。 (如果你想让它变得简单,只需重新创建数组)并开始播放数组中的firstObject(url),将它相应地添加到你的播放器中。

4:播放器完成播放后,您可以开始播放下一个对象,将其从NSMutableArray 添加到播放器,方法与上述相同。

遵循上述步骤将避免多个玩家同时玩,以及其他好处(例如避免同时加载多个 URL 等)

您可能需要一些变量来检查 currentPlayingObject 以确定哪个是下一个,可能是int,并检查如果它是最后播放的项目,您不会尝试从数组中加载新项目,以避免在访问不存在的 objectAtIndex 时崩溃。

【讨论】:

嗯,我已经用通知观察者重写了代码,但是我收到了多个错误...你能告诉我上面的代码应该是什么样子吗?我也很难理解您所说的“更改同一个播放器的项目/网址并开始播放”/ @rebecca87 对不起,我错了,我把你的播放器误认为是 AVPlayer。我已经更新了答案。不幸的是,我没有用 Swift 编写代码,但如果你按照我写的内容进行操作,它应该非常简单。 感谢您的帮助。我会尝试重写我的代码。! NP,它应该非常简单干净,不那么混乱,我也添加了一个关于如何为你创建 NSMutableArray 的链接,(我认为它应该在新的 swift3 中工作) 谢谢,我会检查的:)

以上是关于使用 AVAudioPlayer 播放多个音频文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVAudioPlayer 播放多个音频文件

如何用AVAudioPlayer依次播放多个音频文件

如何在 AVAudioPlayer 中循环播放多个音频文件?

如何同时播放多个音频文件

多个音频文件同时 iphone

如何在 iOS 4 中在后台播放多个音频文件?