ไม่มีตัวแทน AVPlayer? จะติดตามเมื่อเพลงเล่นจบได้อย่างไร? วัตถุประสงค์ C การพัฒนา iPhone


84

ฉันมองไปรอบ ๆ แต่ไม่พบโปรโตคอลการมอบหมายสำหรับAVPlayer class. สิ่งที่ช่วยให้?

ฉันใช้คลาสย่อยของมันAVQueuePlayerเพื่อเล่นอาร์เรย์AVPlayerItemsแต่ละอันโหลดจาก URL มีวิธีใดบ้างที่ฉันสามารถเรียกใช้เมธอดเมื่อเพลงเล่นจบ ยวดท้ายคิว?

และถ้าเป็นไปไม่ได้มีวิธีใดบ้างที่ฉันสามารถเรียกเมธอดเมื่อเพลง STARTS เล่นหลังจากการบัฟเฟอร์ ฉันกำลังพยายามหาไอคอนโหลดอยู่ที่นั่น แต่ไอคอนนั้นปิดก่อนที่เพลงจะเริ่มจริงแม้ว่าจะเป็นหลังจากการ[audioPlayer play]กระทำก็ตาม

คำตอบ:


152

ใช่คลาส AVPlayer ไม่มีโปรโตคอลตัวแทนเช่น AVAudioPlayer คุณต้องสมัครรับการแจ้งเตือนบน AVPlayerItem คุณสามารถสร้าง AVPlayerItem โดยใช้ URL เดียวกับที่คุณจะส่งต่อไปยัง-initWithURL:AVPlayer

-(void)startPlaybackForItemWithURL:(NSURL*)url {

    // First create an AVPlayerItem
    AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:url];

    // Subscribe to the AVPlayerItem's DidPlayToEndTime notification.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];

    // Pass the AVPlayerItem to a new player
    AVPlayer* player = [[[AVPlayer alloc] initWithPlayerItem:playerItem] autorelease];

    // Begin playback
    [player play]

} 

-(void)itemDidFinishPlaying:(NSNotification *) notification {
    // Will be called when AVPlayer finishes playing playerItem
}

1
อย่าลืมใช้itemDidFinishPlaying:เช่นกับโคลอน จากNSNotificationCenterเอกสารประกอบ: เมธอดที่ระบุโดย notificationSelector ต้องมีหนึ่งอาร์กิวเมนต์เดียวเท่านั้น (อินสแตนซ์NSNotification)
Rudolf Adamkovič

@RudolfAdamkovic ขอบคุณสำหรับบันทึก - ฉันแก้ไขคำตอบตามนั้น
arexx

8

ใช่. เพิ่มผู้สังเกตการณ์ KVO ให้กับสถานะหรืออัตราของผู้เล่น:

- (IBAction)go {
   self.player = .....
   self.player.actionAtItemEnd = AVPlayerActionStop;
   [self.player addObserver:self forKeyPath:@"rate" options:0 context:0]; 
}

- (void)stopped {
    ...
    [self.player removeObserver:self]; //assumes we are the only observer
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == 0) {
        if(player.rate==0.0) //stopped
            [self stopped];
    }
    else
        [super observeVal...];
}

โดยพื้นฐานแล้วนั่นแหล่ะ

คำเตือน: ฉันเขียนไว้ที่นี่ดังนั้นฉันจึงไม่ได้ตรวจสอบว่ารหัสนั้นดีหรือไม่ ฉันไม่เคยใช้ AVPlayer มาก่อน แต่มันควรจะถูกต้อง


จะลบผู้สังเกตการณ์ @ "อัตรา" ได้อย่างไร
Saumil Shah

ฉันได้รับคำสั่งในการแก้ไขว่าฉันต้องสังเกตอัตราอย่างแน่นอน ดัดแปลง
Daij-Djan

4
ปัญหาเกี่ยวกับแนวทางนี้คือจะคิดว่าการหยุดชั่วคราวเป็นจุดสิ้นสุดของดนตรี อัตราที่หยุดชั่วคราวเป็นศูนย์เหมือนตอนท้าย
C6Silver

5

Swift 3 - ฉันเพิ่มผู้สังเกตการณ์AVPlayerItemทุกครั้งที่เพิ่มวิดีโอลงในเครื่องเล่น:

func playVideo(url: URL) {
  let playerItem = AVPlayerItem(asset: AVURLAsset(url: someVideoUrl))
  NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidPlayToEndTime), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)
  self.player.replaceCurrentItem(with: playerItem)
  self.player.play()
}

func playerItemDidPlayToEndTime() {
  // load next video or something
}

1

มีข้อมูลมากมายในคู่มือการเขียนโปรแกรม AVFoundationของ Apple docs (ดูส่วนการตรวจสอบการเล่น) มันดูเหมือนจะเป็นส่วนใหญ่ผ่าน KVO ดังนั้นคุณอาจต้องการที่จะแปรงขึ้นบนว่าถ้าคุณไม่คุ้นเคยเกินไป (มีคำแนะนำสำหรับผู้ที่ไปที่สำคัญราคาสังเกต ProgrammingGuide


4
ขอบคุณก่อนอื่นฉันทำให้มันทำงานได้โดยการตรวจสอบเวลาผ่าน KVO แต่จากนั้นฉันก็ใช้ AVPlayerItemDidPlayToEndTimeNotification เนื่องจากมันสะอาดกว่าและใช้โปรเซสเซอร์น้อยกว่า
Tyler

1
การผสมผสานที่บ้าคลั่งของ NSNotificationCenter, KVO และแบบบล็อกในนั้น นึกถึง Apple!
CupawnTae

1

ฉันใช้อันนี้และได้ผล:

_player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:_playingAudio.url]];
CMTime endTime = CMTimeMakeWithSeconds(_playingAudio.duration, 1);
timeObserver = [_player addBoundaryTimeObserverForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:endTime]] queue:NULL usingBlock:^(void) {
    [_player removeTimeObserver:timeObserver];
    timeObserver = nil;
    //TODO play next sound
}];
[self play];

_playingAudioคลาสที่กำหนดเองของฉันอยู่ที่ไหนพร้อมคุณสมบัติบางอย่างและtimeObserverเป็นidไอวาร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.