Ios 检查AVPlayer的播放状态
有没有办法知道Ios 检查AVPlayer的播放状态,ios,objective-c,iphone,avfoundation,avplayer,Ios,Objective C,Iphone,Avfoundation,Avplayer,有没有办法知道AVPlayer播放是否已暂停或已结束?获取项目结束通知(通过): [[NSNotificationCenter defaultCenter] addObserver: 选择器:@selector() 名称:AVPlayerItemDidPlayToEndTimeNotification 对象:; 要跟踪播放,您可以: 通过使用addPeriodicTimeObserverForInterval:queue:usingBlock:或addBoundaryTimeObserverF
AVPlayer
播放是否已暂停或已结束?获取项目结束通知(通过):
[[NSNotificationCenter defaultCenter]
addObserver:
选择器:@selector()
名称:AVPlayerItemDidPlayToEndTimeNotification
对象:;
要跟踪播放,您可以:
通过使用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];
}];
//假设一个属性:@property(retain)id playerObserver;
Float64 durationSeconds=CMTimeGetSeconds([duration]);
CMTime firstThird=CMTimeMakeWithSeconds(持续时间秒/3.0,1);
CMTime secondThird=CMTimeMakeWithSeconds(持续时间秒*2.0/3.0,1);
NSArray*times=[NSArray ARRAY WITH OBJECTS:[NSValue VALUE WITHCMTIME:FIRSTNERD]、[NSValue VALUE WITHCMTIME:SECONTHERD]、nil];
self.playerObserver=[addBoundaryTimeObserverForTimes:times队列:NULL usingBlock:^{
//为队列传递NULL指定主队列。
NSString*timeDescription=(NSString*)CMTimeCopyDescription(NULL,[self.player currentTime]);
NSLog(@“通过%@”的边界,时间描述);
[时间描述发布];
}];
您可以通过以下方式判断它正在播放:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Swift 3扩展:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
对于Swift: AVPlayer: 更新:
player.rate>0
条件更改为player.rate!=0
因为如果视频反向播放,它可能是负片,这要感谢朱利安的指出注意:这可能与上面(Maz)的答案相同,但使用Swift'!player.error'给了我一个编译器错误,因此您必须在Swift中使用'player.error==nil'检查错误。(因为error属性不是'Bool'类型) AVAudioPlayer: AVQueuePlayer:
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
}
}
}
当玩家到达终点时,别忘了让他停下来:
self.player.actionAtItemEnd=AVPlayerActionAtItemEndPause代码>maxkonovalov的Swift版本回答如下:
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
及
重写函数observeValueForKeyPath(键路径:String?,对象的类型:AnyObject?,更改:[String:AnyObject]?,上下文:UnsafeMutablePointer){
如果keyPath==“速率”{
如果let rate=将[NSKeyValueChangeNewKey]更改为浮点数{
如果速率==0.0{
打印(“播放停止”)
}
如果速率==1.0{
打印(“正常播放”)
}
如果速率==-1.0{
打印(“反向播放”)
}
}
}
}
谢谢maxkonovalov 根据maz的回答进行Swift扩展
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
在iOS10中,现在有一个内置属性:timeControlStatus
例如,此功能根据avPlayer的状态播放或暂停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
不是检查视频是否正在播放(可能会暂停)的方法。从费率的文档中
:
指示所需的播放速率;0.0表示“暂停”,1.0表示希望以当前项目的自然速度玩
关键词“渴望播放”-速率1.0
并不意味着视频正在播放。
自iOS 10.0以来的解决方案是使用AVPlayerTimeControlStatus
,这可以在AVPlayer
timeControlStatus
属性上观察到
[self.player addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:NULL];
iOS 10.0(9.0、8.0等)之前的解决方案是推出自己的解决方案速率0.0
表示视频暂停。当<代码>速率!=0.0
表示视频正在播放或暂停。
您可以通过以下方式观察玩家时间来找出差异:func addPeriodicTimeObserver(forInterval interval:CMTime,queue:DispatchQueue?,使用block:@escaping(CMTime)->Void)->Any
块返回CMTime
中的当前播放机时间,因此将lastTime
(上次从块接收的时间)和currentTime
(块刚刚报告的时间)进行比较,可以判断播放机是正在播放还是暂停。例如,如果lastTime==currentTime
和rate!=0.0,则播放机已暂停
正如其他人所指出的,确定播放是否已完成由AVPlayerItemDidPlayToEndTimeNotification
指示。当前使用swift 5检查播放器是否正在播放或暂停最简单的方法是检查.timeControlStatus变量
player.timeControlStatus == .paused
player.timeControlStatus == .playing
答案是客观的C
不一定,它不会处理播放器由于文件中的错误而暂停的情况。我发现了一些困难的事情…正如德莫特所说,如果你在飞行模式下尝试播放某些东西,AVPlayer速率仍然设置为1.0,因为这意味着要播放。AVPlayer有一个错误属性,只需检查它是否为零,以及检查速率是否为0:)注意,答案已更新,以防止@Dermot场景。
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
@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)
}
}
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)
}
player.timeControlStatus == .paused
player.timeControlStatus == .playing
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