Jawaban:
Untuk mendapatkan pemberitahuan untuk mencapai akhir item (melalui Apple ):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
Dan untuk melacak permainan Anda dapat:
"track perubahan di posisi playhead dalam suatu objek AVPlayer" dengan menggunakan addPeriodicTimeObserverForInterval: antrian: usingBlock: atau addBoundaryTimeObserverForTimes: antrian: usingBlock: .
Contohnya dari 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:
, dan tidak menanganinya dengan benar. Cara yang lebih dapat diandalkan bagi saya adalah melacak AVPlayer
status menggunakan KVO. Lihat jawaban saya di bawah untuk detail lebih lanjut: stackoverflow.com/a/34321993/3160561
AVPlayerItemFailedToPlayToEndTimeNotification
Anda dapat membedakannya dengan menggunakan:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Ekstensi Swift 3:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
- [AVPlayer setRate:-1.0]
), karena -1.0
kurang dari 0.
Di iOS10, ada properti bawaan untuk ini sekarang: timeControlStatus
Misalnya, fungsi ini memutar atau menjeda avPlayer berdasarkan statusnya dan memperbarui tombol putar / jeda dengan tepat.
@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)
}
}
Adapun pertanyaan kedua Anda, untuk mengetahui apakah avPlayer mencapai akhir, hal termudah yang harus dilakukan adalah mengatur notifikasi.
NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)
Saat video mencapai akhir, misalnya, Anda dapat memundurkannya ke awal video dan mengatur ulang tombol Jeda ke Putar.
@objc func didPlayToEnd() {
aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
}
Contoh ini berguna jika Anda membuat kontrol Anda sendiri, tetapi jika Anda menggunakan AVPlayerViewController, kontrol tersebut sudah ada di dalamnya.
rate
adalah TIDAK cara untuk memeriksa apakah video yang diputar (bisa terhenti). Dari dokumentasi rate
:
Menunjukkan kecepatan pemutaran yang diinginkan; 0,0 berarti "dijeda", 1,0 menunjukkan keinginan untuk bermain dengan kecepatan alami dari item saat ini.
Kata kunci "keinginan untuk bermain" - tingkat 1.0
tidak berarti video sedang diputar.
Solusi sejak iOS 10.0 adalah menggunakan AVPlayerTimeControlStatus
yang dapat diamati di AVPlayer
timeControlStatus
properti.
Solusi sebelum iOS 10.0 (9.0, 8.0 dll.) Adalah menggulung solusi Anda sendiri. Nilai rata 0.0
-rata video dijeda. Jika rate != 0.0
itu berarti video sedang diputar atau terhenti.
Anda dapat mengetahui perbedaannya dengan mengamati waktu pemain melalui: func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
Blok mengembalikan waktu pemain saat ini masuk CMTime
, jadi perbandingan lastTime
(waktu yang terakhir diterima dari blok) dan currentTime
(waktu blok baru saja dilaporkan) akan memberi tahu apakah pemain itu bermain atau terhenti. Misalnya, jika lastTime == currentTime
dan rate != 0.0
, maka pemain terhenti.
Sebagaimana dicatat oleh orang lain, mencari tahu apakah pemutaran telah selesai ditunjukkan dengan AVPlayerItemDidPlayToEndTimeNotification
.
Alternatif yang lebih dapat diandalkan NSNotification
adalah menambahkan diri Anda sebagai pengamat ke rate
properti pemain .
[self.player addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:NULL];
Kemudian periksa apakah nilai baru untuk kecepatan yang diamati adalah nol, yang berarti pemutaran berhenti karena beberapa alasan, seperti mencapai akhir atau terhenti karena buffer kosong.
- (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
}
}
}
Sebagai rate == 0.0
contoh, untuk mengetahui apa sebenarnya yang menyebabkan pemutaran berhenti, Anda dapat melakukan pemeriksaan berikut:
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
}
Dan jangan lupa untuk membuat pemain Anda berhenti saat mencapai akhir:
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
AVPlayerItemFailedToPlayToEndTimeNotification
. Jika kesalahan ini terjadi, tidak akan pernah mencapai akhir zaman. Atau membaca jawaban maz, tambahkan cek untuk kode Anda player.error != nil
, dalam hal ini pemutaran telah "berakhir" karena kesalahan.
AVPlayerItemDidPlayToEndTimeNotification
?
Untuk Swift :
AVPlayer :
let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
println("playing")
}
Pembaruan :
player.rate > 0
kondisi berubah menjadi player.rate != 0
karena jika video diputar terbalik dapat menjadi negatif berkat Julian karena telah menunjukkan.
Catatan : Ini mungkin terlihat sama seperti di atas (jawaban Maz) tetapi di Swift '! Player.error' memberi saya kesalahan kompiler sehingga Anda harus memeriksa kesalahan menggunakan 'player.error == nil' di Swift. (Karena properti kesalahan bukan tipe '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
), karena -1.0 kurang dari 0.
Perpanjangan cepat berdasarkan jawaban oleh maz
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
Versi Swift dari jawaban maxkonovalov adalah ini:
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
dan
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")
}
}
}
}
Terima kasih maxkonovalov!
nil
! Tapi saya perlu tahu kapan tampilan dimulai (bukan berakhir). Ada cara untuk melakukan itu?
Jawabannya adalah Tujuan 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