Відповіді:
Щоб отримати повідомлення про досягнення кінця товару (через Apple ):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
А відстежувати гру ви можете:
"відстежувати зміни в позиції відтворення в об'єкті AVPlayer", використовуючи addPeriodicTimeObserverForInterval: черга: usingBlock: або addBoundaryTimeObserverForTimes: черга: 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];
}];
-replaceCurrentItemWithPlayerItem:
, і не обробляєте його належним чином. Більш надійним способом для мене є відстеження AVPlayer
статусу за допомогою KVO. Дивіться мою відповідь нижче, щоб отримати докладнішу інформацію: stackoverflow.com/a/34321993/3160561
AVPlayerItemFailedToPlayToEndTimeNotification
Ви можете сказати, що це гра, використовуючи:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Розширення Swift 3:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
- [AVPlayer setRate:-1.0]
), тому що -1.0
менше 0.
В iOS10 зараз існує вбудована властивість: timeControlStatus
Наприклад, ця функція відтворює або призупиняє 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)
}
}
Що стосується вашого другого питання, щоб знати, чи досяг avVlayer до кінця, найпростіше зробити налаштування сповіщення.
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
це НЕ спосіб , щоб перевірити , чи є відео відтворення (він може припинятися). З документації 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
.
Більш надійною альтернативою 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
, щоб знати, що саме спричинило зупинку відтворення, можна виконати такі перевірки:
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;
AVPlayerItemFailedToPlayToEndTimeNotification
. Якщо ця помилка трапиться, ніколи не досягне кінця часу. Або, читаючи відповідь maz, додайте до свого коду чек player.error != nil
, і в цьому випадку відтворення закінчилося через помилку.
AVPlayerItemDidPlayToEndTimeNotification
?
Для Swift :
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" давав мені помилку компілятора, тому вам доведеться перевірити помилку за допомогою "player.error == nil" у Swift. (Тому що властивість помилки не належить до типу "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
}
}
player.rate = -1.0
), оскільки -1,0 менше 0.
Швидке розширення на основі відповіді 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")
}
}
}
}
Дякую, максконовалов!
nil
! Але мені потрібно знати, коли погляд починається (а не закінчується). Будь-який спосіб це зробити?
Відповідь - мета С
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