มีวิธีใดที่จะทราบได้ว่าการAVPlayer
เล่นหยุดชะงักหรือถึงจุดสิ้นสุดแล้ว?
มีวิธีใดที่จะทราบได้ว่าการAVPlayer
เล่นหยุดชะงักหรือถึงจุดสิ้นสุดแล้ว?
คำตอบ:
หากต้องการรับการแจ้งเตือนเมื่อไปถึงจุดสิ้นสุดของรายการ (ผ่านApple ):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
และในการติดตามการเล่นคุณสามารถ:
"ติดตามการเปลี่ยนแปลงตำแหน่งของตัวชี้ตำแหน่งในออบเจ็กต์ AVPlayer" โดยใช้addPeriodicTimeObserverForInterval: que: usingBlock:หรือaddBoundaryTimeObserverForTimes: que: usingBlock: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)
}
}
สำหรับคำถามที่สองของคุณหากต้องการทราบว่า avPlayer ถึงจุดสิ้นสุดหรือไม่สิ่งที่ง่ายที่สุดคือตั้งค่าการแจ้งเตือน
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
เพราะหากเล่นวิดีโอย้อนกลับอาจเป็นลบได้ขอบคุณJulian ที่ชี้ให้เห็น
หมายเหตุ : สิ่งนี้อาจดูเหมือนกับคำตอบด้านบน (ของ Maz) แต่ใน 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))
}
}
คำตอบของ maxkonovalov เวอร์ชัน Swift คือ:
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!
nil
! แต่ฉันต้องรู้ว่าเมื่อใดที่มุมมองเริ่มต้น (ไม่สิ้นสุด) จะทำอย่างไรก็ได้
ขณะนี้มี swift 5 วิธีที่ง่ายที่สุดในการตรวจสอบว่าผู้เล่นกำลังเล่นอยู่หรือหยุดชั่วคราวคือการตรวจสอบตัวแปร. timeControlStatus
player.timeControlStatus == .paused
player.timeControlStatus == .playing
คำตอบคือ Objective 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