如何在 AVAudioPlayer 开始播放音频时准确获取通知?

Posted

技术标签:

【中文标题】如何在 AVAudioPlayer 开始播放音频时准确获取通知?【英文标题】:How to get notification exactly when AVAudioPlayer starts playing audio? 【发布时间】:2019-05-07 09:49:45 【问题描述】:

注意:在将其标记为重复之前,请仔细阅读标题(和问题)。问题是关于AVAudioPlayer 而不是AVPlayer


所以根据AVAudioPlayer的文档

open func play() -> Bool /* sound is played asynchronously. */

我需要在音频开始时准确地向用户显示一个弹出窗口。这不是我们打电话给play()的时候。

当播放器停止播放但没有开始播放时,有一个委托调用:(。

我找不到任何方法来准确知道音频何时开始。有什么方法可以检查吗?

【问题讨论】:

if self.avPlayer?.currentItem?.status == AVPlayerItem.Status.readyToPlay if (self.player?.currentItem?.isPlaybackLikelyToKeepUp) == true // 你可以在这里管理 @Mr.Ahtazaz 请仔细阅读标题。它不是 AVPlayer,它是 AVAudioPlayer。 @Sh_Khan AVPlayerAVAudioPlayer 是两个不相关的类 @iur 您可以先尝试将观察者放在属性上,例如 currentTime @mag_zbc 我也考虑过。在文档中有一个关于playing 属性Important. Do not poll this property to determine when playback has completed, instead implement the specified delegate method. 的注释,所以我不确定我们是否可以使用它来检查播放器是否开始播放。 【参考方案1】:

我也面临同样的问题,只是决定创建一个基于 AVPlayer 的新类:

import AVFoundation
import UIKit

 class AudioManager 

    private init() 

    public static let shared = AudioManager()

    var player: AVPlayer?
    var item: AVPlayerItem?
    var layer: AVPlayerLayer?
    var currentUrl: URL?

    var pauseTime: CMTime?
    var endOfTrackObserver: Any?

    func startPlayContentOf(url: URL?) 

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.playerItemDidReachEnd(notification:)),
                                               name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                               object: self.player?.currentItem)

        guard let newAudioUrl = url else  return 
        let newAudioItem = AVPlayerItem(url: newAudioUrl)


        if let currentUrl = self.currentUrl, currentUrl == newAudioUrl 
            //same track
            if let playing = self.player?.isPlaying, playing == true  
                self.pauseTime = self.player?.currentTime()
                self.pause()
             else 
                self.player = AVPlayer(playerItem: newAudioItem)
                self.player?.volume = 3
                self.player?.seek(to: self.pauseTime ?? CMTime.zero)
                self.layer = AVPlayerLayer(player: self.player)
                self.layer?.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
                self.layer?.backgroundColor = UIColor.clear.cgColor
                guard let layer = self.layer else  return 
                UIApplication.shared.keyWindow?.rootViewController?.view.layer.insertSublayer(layer, at: 0)
                self.play()
            
         else 
            //new track
            self.pauseTime = nil
            self.pause()
            self.player = AVPlayer(playerItem: newAudioItem)
            self.player?.volume = 3
            self.layer = AVPlayerLayer(player: self.player)
            self.layer?.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
            self.layer?.backgroundColor = UIColor.clear.cgColor
            guard let layer = self.layer else  return 
            UIApplication.shared.keyWindow?.rootViewController?.view.layer.insertSublayer(layer, at: 0)
            self.play()
        

        self.currentUrl = newAudioUrl
    

    func playOrPause() 
        guard self.player != nil else  return 
        if self.player!.isPlaying 
            self.player!.pause()
         else 
            self.player?.replaceCurrentItem(with: self.item)
            self.player!.play()
        
    

    func pause() 
        guard self.player != nil else  return 
        self.player!.pause()
    

    func play() 
        guard self.player != nil else  return 
        self.player!.play()
    

    @objc func playerItemDidReachEnd(notification: Notification) 
        self.pauseTime = nil
    


【讨论】:

以上是关于如何在 AVAudioPlayer 开始播放音频时准确获取通知?的主要内容,如果未能解决你的问题,请参考以下文章

AVAudioPlayer 正在再次播放而不被称为播放。

暂停/启动 AVAudioPlayer 无故障弹出

iOS 在特定时间停止音频播放(AVAudioPlayer 结束时间)

使用 AVAudioPlayer 重复音频播放

如何确切地知道为啥声音开始播放?

iOS AvPlayer AvAudioPlayer音频的后台播放问题