Yanıtlar:
Bir öğenin sonuna ulaşıldığına dair bildirim almak için ( Apple aracılığıyla ):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
Çalmayı izlemek için şunları yapabilirsiniz:
addPeriodicTimeObserverForInterval: queue: usingBlock: veya addBoundaryTimeObserverForTimes: queue: usingBlock: kullanarak "bir AVPlayer nesnesinde oynatma kafasının konumundaki değişiklikleri izleyin" .
Örnek Apple'dan:
// 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:
ve düzgün şekilde kullanmazsanız, bildirimler sorunlara neden olabilir . Benim için daha güvenilir bir yol, AVPlayer
KVO kullanarak 'ın durumunu izlemektir. Daha fazla ayrıntı için aşağıdaki
AVPlayerItemFailedToPlayToEndTimeNotification
Oynadığını şunu kullanarak anlayabilirsiniz:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Swift 3 uzantısı:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
- [AVPlayer setRate:-1.0]
) video görüntüsü oynatırken çalışmayacak.-1.0
İOS10'da bunun için yerleşik bir özellik var: timeControlStatus
Örneğin bu işlev, durumuna göre avPlayer'ı oynatır veya duraklatır ve oynat / duraklat düğmesini uygun şekilde günceller.
@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)
}
}
İkinci sorunuza gelince, avPlayer'ın sona ulaşıp ulaşmadığını bilmek için yapılacak en kolay şey bir bildirim ayarlamak olacaktır.
NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)
Örneğin, sona geldiğinde videonun başlangıcına geri sarabilir ve Duraklat düğmesini Oynat olarak sıfırlayabilirsiniz.
@objc func didPlayToEnd() {
aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
}
Bu örnekler, kendi kontrollerinizi oluşturuyorsanız kullanışlıdır, ancak bir AVPlayerViewController kullanıyorsanız, o zaman kontroller yerleşik olarak gelir.
rate
olduğu DEĞİL video olup olmadığını kontrol etmek yolu oynarken (araba durdu olabilir). Belgelerden rate
:
İstenen oynatma oranını gösterir; 0.0 "duraklatıldı" anlamına gelir, 1.0 ise mevcut öğenin doğal hızında oynatma isteğini gösterir.
Anahtar kelimeler "oynatma isteği" - oranı 1.0
videonun oynatıldığı anlamına gelmez.
İOS 10.0'dan beri çözüm AVPlayerTimeControlStatus
, AVPlayer
timeControlStatus
mülk üzerinde gözlemlenebilen kullanmaktır .
İOS 10.0'dan önceki çözüm (9.0, 8.0 vb.) Kendi çözümünüzü kullanmaktır. Oran 0.0
, videonun duraklatıldığı anlamına gelir. Ne zaman rate != 0.0
o video ya oynama olduğu anlamına gelir veya takıldı.
Oyuncu zamanını aşağıdaki yollarla gözlemleyerek farkı öğrenebilirsiniz: func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
Blok, içinde geçerli oyuncu zamanını döndürür CMTime
, bu nedenle lastTime
(bloktan en son alınan currentTime
zaman ) ve (bloğun henüz bildirildiği zaman) bir karşılaştırması, oyuncunun oynayıp oynamadığını gösterir. Örneğin, eğer lastTime == currentTime
ve rate != 0.0
, sonra oyuncu durdu.
Başkaları tarafından da belirtildiği gibi, oynatmanın bitip bitmediğini anlamak ile belirtilir AVPlayerItemDidPlayToEndTimeNotification
.
Daha güvenilir bir alternatif, NSNotification
kendinizi oyuncunun rate
mülküne gözlemci olarak eklemektir .
[self.player addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:NULL];
Ardından, gözlemlenen hız için yeni değerin sıfır olup olmadığını kontrol edin; bu, sona ulaşma veya boş arabellek nedeniyle durma gibi bir nedenle oynatmanın durduğu anlamına gelir.
- (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
}
}
}
İçin rate == 0.0
durumunda, tam durağına oynatmayı neyin neden olduğunu bilmek, aşağıdaki kontrolleri yapabilirsiniz:
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
}
Ve sona ulaştığında oynatıcınızı durdurmayı unutmayın:
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
AVPlayerItemFailedToPlayToEndTimeNotification
. Bu hata olursa, hiçbir zaman bitiş zamanına ulaşmaz. Veya maz'ın cevabını okuyarak, kodunuza bir kontrol ekleyin player.error != nil
, bu durumda oynatma, hata nedeniyle "sona erdi".
AVPlayerItemDidPlayToEndTimeNotification
?
İçin Swift :
AVPlayer :
let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
println("playing")
}
Güncelleme :
player.rate > 0
durum olarak değiştirildi, player.rate != 0
çünkü video ters yönde oynatılıyorsa, Julian sayesinde işaret ettiği için olumsuz olabilir .
Not : Bu, yukarıdaki (Maz'in) cevabı ile aynı görünebilir ancak Swift'de '! Player.error' bana bir derleyici hatası veriyordu, bu nedenle Swift'de 'player.error == nil' kullanırken hata olup olmadığını kontrol etmelisiniz. (Çünkü hata özelliği 'Bool' türünde değil)
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
, çünkü -1.0 0'dan küçük.
Maz tarafından verilen cevaba dayalı hızlı uzantı
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
Maxkonovalov'un cevabının Swift versiyonu şudur:
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
ve
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")
}
}
}
}
Teşekkürler maxkonovalov!
nil
! Ancak görünümün ne zaman başladığını (bitmediğini) bilmem gerekiyor. Bunu yapmanın bir yolu var mı?
Cevap Hedef 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
}
player.timeControlStatus == AVPlayer.TimeControlStatus.playing