Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 537 Vote(s) - 3.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Check play state of AVPlayer

#1
Is there a way to know whether an `AVPlayer` playback has stalled or reached the end?
Reply

#2
To get notification for reaching the end of an item (via [Apple][1]):

[[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:**.

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];
}];


[1]:

[To see links please register here]

Reply

#3
For **Swift**:


*AVPlayer*:

let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
println("playing")
}
**Update**:<br>
`player.rate > 0` condition changed to `player.rate != 0` because if video is playing in reverse it can be negative thanks to *Julian* for pointing out. <br>
**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)

*AVAudioPlayer:*

if let theAudioPlayer = appDelegate.audioPlayer {
if (theAudioPlayer.playing) {
// playing
}
}
*AVQueuePlayer:*

if let theAudioQueuePlayer = appDelegate.audioPlayerQueue {
if (theAudioQueuePlayer.rate != 0 && theAudioQueuePlayer.error == nil) {
// playing
}
}
Reply

#4
A more reliable alternative to `NSNotification` is to add yourself as observer to player's `rate` property.

[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:

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;`
Reply

#5
The Swift version of maxkonovalov's answer is this:

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!
Reply

#6
Swift extension based on the answer by maz

extension AVPlayer {

var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
Reply

#7
You can tell it's playing using:

AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}

Swift 3 extension:

extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
Reply

#8
`rate` is **NOT** the way to check whether a video is *playing* (it could stalled). From documentation of `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.

Key words "desire to play" - **a rate of `1.0` does not mean the video is playing.**

The solution since iOS 10.0 is to use `AVPlayerTimeControlStatus` which can be observed on `AVPlayer` `timeControlStatus` property.

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 *or* is stalled.**

You can find out the difference by observing player time via: `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.

As noted by others, figuring out whether playback has finished is indicated by `AVPlayerItemDidPlayToEndTimeNotification`.
Reply

#9
Currently with swift 5 the easiest way to check if the player is playing or paused is to check the *.timeControlStatus* variable.

player.timeControlStatus == .paused
player.timeControlStatus == .playing

Reply

#10
player.timeControlStatus == AVPlayer.TimeControlStatus.playing
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through