ios - 使用 AVAudioPlayer 播放多个音频文件

标签 ios swift xcode avaudioplayer

我在主 Storyboard上创建了 3 个 UIButton。

当我按下“Button1”或“Button2”时,每个按钮都会播放一个音频文件(“播放器 1”、“播放器 2”。)并且在播放音频时,UIButton 设置为已选择

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

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

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

I created image to make it easier to understand

    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")
        }

最佳答案

编辑:This is the method对于 AVAudioPlayer

所以基本上:

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

2: Create an NSMutableArray 与您要播放的对象。

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

4: 当播放器结束播放时,您可以开始播放下一个对象,将其从 NSMutableArray 添加到您的播放器中,方法与上述相同。

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

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

关于ios - 使用 AVAudioPlayer 播放多个音频文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42324487/

相关文章:

iOS - 如何在从远程服务流式传输时在 UITextView 中开始新行

swift - 命令编译 Storyboard 失败,退出代码非零

ios - 使用容器 View 时无法隐藏选项卡栏

iphone - 将前面带有标签的 NSString 中的单词分开

ios - 我可以检测相机是否使用 GPUImage 运行吗?

ios - UIScrollView 相对于子 ViewController 的偏移量

ios - 在 Swift 中进行简单的 Date() 操作时崩溃

ios - 具有 2 个以上 channel 的 AVAssetWriterInput

ios - 多 View 转一 View ,我怎么回发件人

ios - 在 Swift 中过滤自定义对象数组