Pas de délégué AVPlayer? Comment suivre la fin de la lecture de la chanson? Développement d'iPhone Objective C

84

J'ai regardé autour de moi mais je ne trouve pas de protocole de délégué pour le AVPlayer class. Ce qui donne?

J'utilise sa sous-classe,, AVQueuePlayerpour lire un tableau de AVPlayerItems, chacun chargé à partir d'une URL. Puis-je appeler une méthode à la fin de la lecture d'une chanson? Notamment à la fin de la file d'attente?

Et si ce n'est pas possible, est-ce que je pourrais appeler une méthode lorsque la chanson COMMENCE à jouer, après la mise en mémoire tampon? J'essaie d'y insérer une icône de chargement, mais cela désactive l'icône avant que la musique ne commence réellement, même si c'est après l' [audioPlayer play]action.

Tyler
la source

Réponses:

152

Oui, la classe AVPlayer n'a pas de protocole délégué comme AVAudioPlayer. Vous devez vous abonner aux notifications sur un AVPlayerItem. Vous pouvez créer un AVPlayerItem en utilisant la même URL que vous transmettriez autrement -initWithURL:sur 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
}
arexx
la source
1
Assurez-vous d'utiliser itemDidFinishPlaying:, par exemple avec deux-points. De la NSNotificationCenterdocumentation: La méthode spécifiée par notificationSelector doit avoir un et un seul argument (une instance de NSNotification).
Rudolf Adamkovič
@RudolfAdamkovic Merci pour la note - j'ai modifié ma réponse en conséquence.
arexx
8

Oui. Ajouter un observateur KVO au statut ou au taux du joueur:

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

Donc, fondamentalement, c'est tout.

Avertissement: je l'ai écrit ici, donc je n'ai pas vérifié si le code était bon. AUSSI, je n'ai jamais utilisé AVPlayer auparavant, mais cela devrait être à peu près correct.

Daij-Djan
la source
Comment supprimer l'observateur @ "rate"?
Saumil Shah
On m'a dit dans une édition que je devais observer le taux à coup sûr. adapté
Daij-Djan
4
Un problème avec cette approche est qu'elle pensera qu'une pause est la fin de la musique. Le taux à la pause est nul comme il le serait à la fin.
C6Silver
5

Swift 3 - J'ajoute un observateur à AVPlayerItemchaque fois que j'ajoute une vidéo au lecteur:

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
la source
1

Il y a beaucoup d'informations dans le guide de programmation d' Apple docs AVFoundation (recherchez la section de lecture de surveillance). Il semble que ce soit principalement via KVO, donc vous voudrez peut-être revoir cela si vous n'êtes pas trop familier (il existe un guide pour cela dans le guide de programmation d'observation des valeurs clés .

Paul.s
la source
4
Merci, je l'ai d'abord fait fonctionner en surveillant l'heure via KVO, mais j'ai ensuite implémenté AVPlayerItemDidPlayToEndTimeNotification car il est plus propre et moins gourmand en processeur.
Tyler
1
Un mélange un peu fou de NSNotificationCenter, KVO et basé sur des blocs. Décidez Apple!
CupawnTae
1

J'utilise celui-ci, et ça marche:

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

_playingAudioest ma classe personnalisée avec quelques propriétés et timeObserverest idivar.

Timur Mustafaev
la source