Kein AVPlayer-Delegierter? Wie kann ich verfolgen, wann der Song fertig ist? Ziel C iPhone Entwicklung

84

Ich habe mich umgesehen, aber ich kann kein Delegatenprotokoll für das finden AVPlayer class. Was gibt?

Ich verwende seine Unterklasse, AVQueuePlayerum ein Array von AVPlayerItemsjeweils von einer URL geladenen abzuspielen . Kann ich eine Methode aufrufen, wenn ein Song fertig ist? Besonders am Ende der Warteschlange?

Und wenn das nicht möglich ist, gibt es eine Möglichkeit, eine Methode aufzurufen, wenn der Song nach dem Puffern abgespielt wird? Ich versuche dort ein Ladesymbol zu finden, aber es schaltet das Symbol aus, bevor die Musik tatsächlich beginnt, obwohl es nach der [audioPlayer play]Aktion ist.

Tyler
quelle

Antworten:

152

Ja, die AVPlayer-Klasse verfügt nicht über ein Delegate-Protokoll wie der AVAudioPlayer. Sie müssen Benachrichtigungen auf einem AVPlayerItem abonnieren. Sie können ein AVPlayerItem mit derselben URL erstellen, an die Sie es sonst -initWithURL:auf AVPlayer übergeben würden.

-(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
}
arexx
quelle
1
Verwenden Sie es unbedingt itemDidFinishPlaying:, z. B. mit Doppelpunkt. Aus der NSNotificationCenterDokumentation: Die von notificationSelector angegebene Methode darf nur ein Argument (eine Instanz von NSNotification) enthalten.
Rudolf Adamkovič
@ RudolfAdamkovic Danke für den Hinweis - ich habe meine Antwort entsprechend bearbeitet.
Arexx
8

Ja. Fügen Sie dem Status oder der Rate des Spielers einen KVO-Beobachter hinzu:

- (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...];
}

Im Grunde ist es das.

Haftungsausschluss: Ich habe das hier geschrieben, also habe ich nicht überprüft, ob der Code gut ist. AUCH ich habe AVPlayer noch nie benutzt, aber es sollte ungefähr richtig sein.

Daij-Djan
quelle
Wie entferne ich den Beobachter "rate"?
Saumil Shah
Mir wurde in einer Bearbeitung gesagt, dass ich die Rate sicher beobachten muss. angepasst
Daij-Djan
4
Ein Problem bei diesem Ansatz ist, dass eine Pause das Ende der Musik darstellt. Die Rate bei Pause ist wie am Ende Null.
C6Silver
5

Swift 3 - Ich füge AVPlayerItemjedes Mal, wenn ich dem Player ein Video hinzufüge, einen Beobachter hinzu:

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
}
Budidino
quelle
1

Das AVFoundation-Programmierhandbuch für Apple-Dokumente enthält viele Informationen (siehe Abschnitt zur Wiedergabe der Überwachung). Es scheint hauptsächlich über KVO zu sein, daher möchten Sie dies möglicherweise auffrischen, wenn Sie nicht zu vertraut sind (es gibt eine Anleitung dazu zu Key Value Observing ProgrammingGuide) .

Paul.s
quelle
4
Vielen Dank, zuerst habe ich es funktioniert, indem ich die Zeit über KVO überwacht habe, aber dann habe ich die AVPlayerItemDidPlayToEndTimeNotification implementiert, da sie sauberer und weniger prozessorintensiv ist.
Tyler
1
Eine verrückte Mischung aus NSNotificationCenter, KVO und blockbasiert. Entscheide dich für Apple!
CupawnTae
1

Ich benutze dieses und es funktioniert:

_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];

Wo _playingAudioist meine benutzerdefinierte Klasse mit einigen Eigenschaften und timeObserverist idivar.

Timur Mustafaev
quelle