Проверьте состояние воспроизведения AVPlayer
есть ли способ узнать, является ли AVPlayer
воспроизведение остановилось или дошло до конца?
8 ответов:
чтобы получить уведомление о достижении конца элемента (через Яблоко):
[[NSNotificationCenter defaultCenter] addObserver:<self> selector:@selector(<#The selector name#>) name:AVPlayerItemDidPlayToEndTimeNotification object:<#A player item#>];
и отслеживать воспроизведение вы можете:
"отслеживать изменения положения головки воспроизведения в объекте AVPlayer" с помощью addPeriodicTimeObserverForInterval: queue: usingBlock: или addBoundaryTimeObserverForTimes: queue: usingBlock:.
пример из 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]; }];
Вы можете сказать, что он играет с помощью:
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 btnPlayTap(_ 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)
когда он дойдет до конца, например, вы можете перемотать его на начало видео и сброс кнопки паузы для воспроизведения.
func didPlayToEnd() { aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1)) btnPlay.setImage(UIImage(named: "control-play"), for: .normal) }
эти примеры полезны, если вы создаете свои собственные элементы управления, но если вы используете AVPlayerViewController, то элементы управления встроены.
более надежная альтернатива
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
case, чтобы узнать, что именно вызвало остановку воспроизведения, вы можете выполнить следующие проверки: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;
на Свифт:
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
потому что, если видео воспроизводится в обратном, он может быть отрицательным, благодаря Юлиан для указывая.
Примечание: это может выглядеть так же, как выше(МАЗ) ответ, но в Swift '!игрок.ошибка "давала мне ошибку компилятора, поэтому вы должны проверить ошибку с помощью" player.error = = nil ' in Быстрый.(потому что свойство 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 } }
rate
и не способ проверить, является ли видео игры (это может заглохнуть). Из документацииrate
:указывает на желаемую скорость воспроизведения; 0.0 означает "приостановлено", 1.0 указывает на желание играть с естественной скоростью текущего элемента.
ключевые слова "желание играть" - в размере
1.0
не означает, что видео воспроизводится.решение с iOS 10.0-это использовать
AVPlayerTimeControlStatus
что можно наблюдать наAVPlayer
timeControlStatus
собственность.решение до iOS 10.0 (9.0, 8.0 и т. д.) свернуть свои собственные решения. в размере
0.0
означает, что видео приостановлено. Когдаrate != 0.0
это означает, что видео либо играть или заглох.вы можете узнать разницу, наблюдая за временем игрока через:
func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
блок возвращает текущее время игрока в
CMTime
, так что сравнениеlastTime
(время последнего получения от Блока) иcurrentTime
(время, которое блок только что сообщил) покажет, играет ли игрок или заглох. Например, еслиlastTime == currentTime
иrate != 0.0
, то игрок заглох.как отметили другие, выяснение того, закончено ли воспроизведение, обозначается
AVPlayerItemDidPlayToEndTimeNotification
.
расширение Swift на основе ответа от maz
extension AVPlayer { var isPlaying: Bool { return ((rate != 0) && (error == nil)) } }
быстрая версия ответа максконовалова такова:
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!