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, AVQueuePlayer
, pour lire un tableau de AVPlayerItems
, chacun chargé à partir d'une URL. Existe-t-il un moyen de faire appel à une méthode à la fin d'une chanson? Notamment à la fin de la file d'attente?
Et si cela n’est pas possible, puis-je appeler une méthode lorsque la chanson commence à jouer, après la mise en mémoire tampon? J'essaie d'obtenir une icône de chargement mais cette icône est désactivée avant que la musique ne commence réellement, même si c'est après le [audioPlayer play]
action.
Oui, la classe AVPlayer n'a pas de protocole de 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 celle que vous auriez sinon transmise à -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
}
Oui. Ajouter un observateur KVO au statut ou à la cote 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.
Disclaimer: J'ai écrit ça 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.
Swift - J'ajoute un observateur à AVPlayerItem
à chaque 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
}
Il y a beaucoup d’informations dans le Apple docs Guide de programmation AVFoundation (recherchez la section de lecture de contrôle). Il semble que ce soit principalement via KVO. rafraîchissez-vous si vous n'êtes pas trop familier (il existe un guide pour cela Key Value Observer ProgrammingGuide .
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];
où _playingAudio
est ma classe personnalisée avec quelques propriétés et timeObserver
est id
ivar.