ios 检查 AVPlayer 的播放状态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5655864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check play state of AVPlayer
提问by Egil
Is there a way to know whether an AVPlayer
playback has stalled or reached the end?
有没有办法知道AVPlayer
播放是否已停止或已结束?
采纳答案by Todd Hopkinson
To get notification for reaching the end of an item (via Apple):
要获得到达项目末尾的通知(通过Apple):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
And to track playing you can:
要跟踪播放,您可以:
"track changes in the position of the playhead in an AVPlayer object" by using addPeriodicTimeObserverForInterval:queue:usingBlock:or addBoundaryTimeObserverForTimes:queue:usingBlock:.
通过使用addPeriodicTimeObserverForInterval:queue:usingBlock:或addBoundaryTimeObserverForTimes:queue:usingBlock: 来“跟踪 AVPlayer 对象中播放头位置的变化” 。
Example is from Apple:
例子来自苹果:
// 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];
}];
回答by maz
You can tell it's playing using:
您可以使用以下命令判断它正在播放:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Swift 3 extension:
斯威夫特 3 扩展:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
回答by Travis M.
In iOS10, there's a built in property for this now: timeControlStatus
在 iOS10 中,现在有一个内置属性:timeControlStatus
For example, this function plays or pauses the avPlayer based on it's status and updates the play/pause button appropriately.
例如,此函数根据 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)
}
}
As for your second question, to know if the avPlayer reached the end, the easiest thing to do would be to set up a notification.
至于你的第二个问题,要知道 avPlayer 是否到达终点,最简单的方法是设置通知。
NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)
When it gets to the end, for example, you can have it rewind to the beginning of the video and reset the Pause button to Play.
例如,当它结束时,您可以让它倒回到视频的开头并将暂停按钮重置为播放。
@objc func didPlayToEnd() {
aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
}
These examples are useful if you're creating your own controls, but if you use a AVPlayerViewController, then the controls come built in.
如果您要创建自己的控件,这些示例很有用,但如果您使用 AVPlayerViewController,则控件是内置的。
回答by kgaidis
rate
is NOTthe way to check whether a video is playing(it could stalled). From documentation of rate
:
rate
是不是要检查视频是否是这样打(这可能停滞不前)。从文档rate
:
Indicates the desired rate of playback; 0.0 means "paused", 1.0 indicates a desire to play at the natural rate of the current item.
指示所需的播放速率;0.0 表示“暂停”,1.0 表示希望以当前项目的自然速率播放。
Key words "desire to play" - a rate of 1.0
does not mean the video is playing.
关键词“播放欲望”——速率为1.0
并不意味着视频正在播放。
The solution since iOS 10.0 is to use AVPlayerTimeControlStatus
which can be observed on AVPlayer
timeControlStatus
property.
自 iOS 10.0 以来的解决方案是使用AVPlayerTimeControlStatus
可以在AVPlayer
timeControlStatus
属性上观察到的。
The solution prior to iOS 10.0 (9.0, 8.0 etc.) is to roll your own solution. A rate of 0.0
means that the video is paused. When rate != 0.0
it means that the video is either playing oris stalled.
iOS 10.0(9.0、8.0 等)之前的解决方案是推出您自己的解决方案。速率0.0
表示视频已暂停。当rate != 0.0
这意味着视频正在播放或停止时。
You can find out the difference by observing player time via: func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
您可以通过以下方式观察玩家时间来找出差异: func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
The block returns the current player time in CMTime
, so a comparison of lastTime
(the time that was last received from the block) and currentTime
(the time that the block just reported) will tell whether the player is playing or is stalled. For example, if lastTime == currentTime
and rate != 0.0
, then the player has stalled.
块在 中返回当前玩家时间CMTime
,因此比较lastTime
(上次从块接收currentTime
的时间)和(块刚刚报告的时间)将判断玩家是在玩游戏还是停顿。例如,如果lastTime == currentTime
和rate != 0.0
,则播放器已停止。
As noted by others, figuring out whether playback has finished is indicated by AVPlayerItemDidPlayToEndTimeNotification
.
正如其他人所指出的,确定播放是否已完成由 表示AVPlayerItemDidPlayToEndTimeNotification
。
回答by maxkonovalov
A more reliable alternative to NSNotification
is to add yourself as observer to player's rate
property.
一个更可靠的替代方法NSNotification
是将自己作为观察者添加到玩家的rate
财产中。
[self.player addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:NULL];
Then check if the new value for observed rate is zero, which means that playback has stopped for some reason, like reaching the end or stalling because of empty buffer.
然后检查观察速率的新值是否为零,这意味着由于某种原因播放已停止,例如到达结尾或由于空缓冲区而停止。
- (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
}
}
}
For rate == 0.0
case, to know what exactly caused the playback to stop, you can do the following checks:
例如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
}
And don't forget to make your player stop when it reaches the end:
并且不要忘记让您的播放器在播放结束时停止:
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
回答by Aks
For Swift:
对于斯威夫特:
AVPlayer:
AV播放器:
let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
println("playing")
}
Update:player.rate > 0
condition changed to player.rate != 0
because if video is playing in reverse it can be negative thanks to Julianfor pointing out.
Note: This might look same as above(Maz's) answer but in Swift '!player.error' was giving me a compiler error so you have to check for error using 'player.error == nil' in Swift.(because error property is not of 'Bool' type)
更新:player.rate > 0
条件更改为,player.rate != 0
因为如果视频反向播放,由于Julian的指出,它可能是负面的。
注意:这可能与上面(Maz 的)答案相同,但在 Swift 中,'!player.error' 给了我一个编译器错误,因此您必须在 Swift 中使用 'player.error == nil' 检查错误。(因为错误属性不是“布尔”类型)
AVAudioPlayer:
AV音频播放器:
if let theAudioPlayer = appDelegate.audioPlayer {
if (theAudioPlayer.playing) {
// playing
}
}
AVQueuePlayer:
AV队列播放器:
if let theAudioQueuePlayer = appDelegate.audioPlayerQueue {
if (theAudioQueuePlayer.rate != 0 && theAudioQueuePlayer.error == nil) {
// playing
}
}
回答by Mark Bridges
Swift extension based on the answer by maz
基于 maz 的答案的 Swift 扩展
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
回答by Mr Stanev
The Swift version of maxkonovalov's answer is this:
maxkonovalov 的答案的 Swift 版本是这样的:
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
and
和
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")
}
}
}
}
Thank you maxkonovalov!
谢谢马克科诺瓦洛夫!
回答by azemi
Currently with swift 5 the easiest way to check if the player is playing or paused is to check the .timeControlStatusvariable.
目前使用 swift 5 检查播放器是否正在播放或暂停的最简单方法是检查.timeControlStatus变量。
player.timeControlStatus == .paused
player.timeControlStatus == .playing
回答by iOS Lifee
Answer is Objective C
答案是目标 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
}