检查AVPlayer的播放状态

| 有没有办法知道ѭ0播放是否停止或结束?     
已邀请:
要获取到达商品末尾的通知(通过Apple):
[[NSNotificationCenter defaultCenter] 
      addObserver:<self>
      selector:@selector(<#The selector name#>)
      name:AVPlayerItemDidPlayToEndTimeNotification 
      object:<#A player item#>];
要跟踪播放,您可以: 通过使用addPeriodicTimeObserverForInterval:queue:usingBlock:或addBoundaryTimeObserverForTimes:queue:usingBlock:来“跟踪AVPlayer对象中播放头位置的变化”。 示例来自苹果:
// Assume a property: @property (retain) id playerObserver;

Float64 durationSeconds = CMTimeGetSeconds([<#An asset#> duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 1);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 1);
NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird], nil];

self.playerObserver = [<#A player#> addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
    // Passing NULL for the queue specifies the main queue.

    NSString *timeDescription = (NSString *)CMTimeCopyDescription(NULL, [self.player currentTime]);
    NSLog(@\"Passed a boundary at %@\", timeDescription);
    [timeDescription release];
}];
    
您可以使用以下命令告诉它正在播放:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
    // player is playing
}
Swift 3扩展名:
extension AVPlayer {
    var isPlaying: Bool {
        return rate != 0 && error == nil
    }
}
    
在iOS10中,现在有一个内置属性:timeControlStatus 例如,此功能根据其状态播放或暂停avPlayer,并适当更新播放/暂停按钮。
@IBAction func btnPlayPauseTap(_ sender: Any) {
    if aPlayer.timeControlStatus == .playing {
        aPlayer.pause()
        btnPlay.setImage(UIImage(named: \"control-play\"), for: .normal)
    } else if aPlayer.timeControlStatus == .paused {
        aPlayer.play()
        btnPlay.setImage(UIImage(named: \"control-pause\"), for: .normal)
    }
}
至于第二个问题,要知道avPlayer是否已结束,最简单的方法是设置一个通知。
NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)
例如,当播放到结尾时,您可以将其倒带到视频的开头,并将“暂停”按钮重置为“播放”。
@objc func didPlayToEnd() {
    aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
    btnPlay.setImage(UIImage(named: \"control-play\"), for: .normal)
}
如果您要创建自己的控件,那么这些示例很有用,但是如果您使用AVPlayerViewController,则控件是内置的。     
rate
不是检查视频是否正在播放的方法(可能会停顿)。从
rate
的文档中:   指示所需的播放速率; 0.0表示“已暂停”,1.0表示希望以当前项目的自然速率播放。 关键字“渴望播放”-ѭ10的比率并不表示视频正在播放。 自iOS 10.0起的解决方案是使用ѭ11,可以在
AVPlayer
timeControlStatus
属性中观察到。 iOS 10.0(9.0、8.0等)之前的解决方案是推出您自己的解决方案。 rate14ѭ的速率表示视频已暂停。当“ 15”时,表示视频正在播放或停顿。 您可以通过以下方式观察玩家时间来找出差异:
func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
该区块以
CMTime
返回当前玩家时间,因此,将ѭ18from(最近一次从区块收到的时间)与
currentTime
(刚刚报告该区块的时间)的比较将表明玩家是在玩还是已停顿。例如,如果
lastTime == currentTime
rate != 0.0
,则说明玩家已停滞。 正如其他人所指出的那样,用“ 22”来指示播放是否完成。     
NSNotification
的一个更可靠的替代方法是将自己添加为玩家
rate
属性的观察者。
[self.player addObserver:self
              forKeyPath:@\"rate\"
                 options:NSKeyValueObservingOptionNew
                 context:NULL];
然后检查观察到的速率的新值是否为零,这意味着播放由于某种原因已停止,例如到达结尾或由于空缓冲区而停止。
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSString *,id> *)change
                       context:(void *)context {
    if ([keyPath isEqualToString:@\"rate\"]) {
        float rate = [change[NSKeyValueChangeNewKey] floatValue];
        if (rate == 0.0) {
            // Playback stopped
        } else if (rate == 1.0) {
            // Normal playback
        } else if (rate == -1.0) {
            // Reverse playback
        }
    }
}
对于
rate == 0.0
情况,要了解到底是什么原因导致播放停止,可以进行以下检查:
if (self.player.error != nil) {
    // Playback failed
}
if (CMTimeGetSeconds(self.player.currentTime) >=
    CMTimeGetSeconds(self.player.currentItem.duration)) {
    // Playback reached end
} else if (!self.player.currentItem.playbackLikelyToKeepUp) {
    // Not ready to play, wait until enough data is loaded
}
并且不要忘记让播放器到达终点时停止播放:
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
    
对于Swift: AVPlayer:
let player = AVPlayer(URL: NSURL(string: \"http://www.sample.com/movie.mov\"))
if (player.rate != 0 && player.error == nil) {
   println(\"playing\")
}
更新:
player.rate > 0
条件更改为
player.rate != 0
,因为如果视频反向播放,由于朱利安指出,它可能为负。 注意:这可能与上面的答案(Maz \'s)相同,但是在Swift \'!player.error \'中给了我一个编译器错误,因此您必须使用\'player.error == nil \'检查错误在Swift中。(因为error属性不是\'Bool \'类型) AVAudioPlayer:
if let theAudioPlayer =  appDelegate.audioPlayer {
   if (theAudioPlayer.playing) {
       // playing
   }
}
AVQueuePlayer:
if let theAudioQueuePlayer =  appDelegate.audioPlayerQueue {
   if (theAudioQueuePlayer.rate != 0 && theAudioQueuePlayer.error == nil) {
       // playing
   }
}
    
基于maz答案的Swift扩展
extension AVPlayer {

    var isPlaying: Bool {
        return ((rate != 0) && (error == nil))
    }
}
    
maxkonovalov的Swift版本的答案是这样的:
player.addObserver(self, forKeyPath: \"rate\", options: NSKeyValueObservingOptions.New, context: nil)
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == \"rate\" {
        if let rate = change?[NSKeyValueChangeNewKey] as? Float {
            if rate == 0.0 {
                print(\"playback stopped\")
            }
            if rate == 1.0 {
                print(\"normal playback\")
            }
            if rate == -1.0 {
                print(\"reverse playback\")
            }
        }
    }
}
谢谢maxkonovalov!     
当前,使用swift 5来检查播放器是播放还是暂停的最简单方法是检查.timeControlStatus变量。
player.timeControlStatus == .paused
player.timeControlStatus == .playing
    
  答案是目标C
if (player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
    //player is playing
}
else if (player.timeControlStatus == AVPlayerTimeControlStatusPaused) {
    //player is pause
}
else if (player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
    //player is waiting to play
}
    
player.timeControlStatus == AVPlayer.TimeControlStatus.playing
    

要回复问题请先登录注册