Check play state of AVPlayer - Printable Version +- 0Day Forums (https://0day.red) +-- Forum: Coding (https://0day.red/Forum-Coding) +--- Forum: Objective-C (https://0day.red/Forum-Objective-C) +--- Thread: Check play state of AVPlayer (/Thread-Check-play-state-of-AVPlayer) Pages:
1
2
|
Check play state of AVPlayer - goodden979 - 07-21-2023 Is there a way to know whether an `AVPlayer` playback has stalled or reached the end? RE: Check play state of AVPlayer - hired91301 - 07-21-2023 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] RE: Check play state of AVPlayer - hectorean916468 - 07-21-2023 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 } } RE: Check play state of AVPlayer - elinaczurpulnnp - 07-21-2023 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;` RE: Check play state of AVPlayer - normanish400920 - 07-21-2023 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! RE: Check play state of AVPlayer - sunday237579 - 07-21-2023 Swift extension based on the answer by maz extension AVPlayer { var isPlaying: Bool { return ((rate != 0) && (error == nil)) } } RE: Check play state of AVPlayer - anticipatorily85089 - 07-21-2023 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 } } RE: Check play state of AVPlayer - curst994 - 07-21-2023 `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`. RE: Check play state of AVPlayer - released632596 - 07-21-2023 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 RE: Check play state of AVPlayer - waterzooi422684 - 07-21-2023 player.timeControlStatus == AVPlayer.TimeControlStatus.playing |