150 votes

Mettre en boucle une vidéo avec AVFoundation AVPlayer ?

Existe-t-il un moyen relativement simple de mettre en boucle une vidéo dans AVFoundation ?

J'ai créé mon AVPlayer et mon AVPlayerLayer comme suit :

avPlayer = [[AVPlayer playerWithURL:videoUrl] retain];
avPlayerLayer = [[AVPlayerLayer playerLayerWithPlayer:avPlayer] retain];

avPlayerLayer.frame = contentView.layer.bounds;
[contentView.layer addSublayer: avPlayerLayer];

et ensuite je joue ma vidéo avec :

[avPlayer play];

La vidéo est bien diffusée mais s'arrête à la fin. Avec le MPMoviePlayerController, tout ce que vous avez à faire, c'est de régler sa fonction repeatMode à la bonne valeur. Il ne semble pas y avoir de propriété similaire sur AVPlayer. Il ne semble pas non plus y avoir de rappel pour me dire quand le film est terminé, afin que je puisse revenir au début et le relire.

Je n'utilise pas MPMoviePlayerController car il présente de sérieuses limitations. Je veux pouvoir lire plusieurs flux vidéo à la fois.

1 votes

Voir cette réponse pour un lien vers un code fonctionnel réel : stackoverflow.com/questions/7822808/

1voto

vp2698 Points 1041

Pour Swift 3 et 4

NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.avPlayer?.currentItem, queue: .main) { _ in
     self.avPlayer?.seek(to: kCMTimeZero)
     self.avPlayer?.play()
}

1voto

Rashid Points 1011

Je n'ai pas pu trouver ma solution parmi les réponses. Il peut être utile d'observer le temps limite spécifié à la durée de l'actif. Lorsque l'observateur est déclenché, cherchez le début et rejouez.

player?.addBoundaryTimeObserver(forTimes: [NSValue(time: asset.duration)], queue: .main) { [weak self] in
    self?.player?.seek(to: .zero, completionHandler: { [weak self] _ in
        self?.player?.play()
    })
}

0voto

James Bush Points 1027

Après avoir chargé la vidéo dans l'AVPlayer (via son AVPlayerItem, bien sûr) :

 [self addDidPlayToEndTimeNotificationForPlayerItem:item];

La méthode addDidPlayToEndTimeNotificationForPlayerItem :

- (void)addDidPlayToEndTimeNotificationForPlayerItem:(AVPlayerItem *)item
{
    if (_notificationToken)
        _notificationToken = nil;

    /*
     Setting actionAtItemEnd to None prevents the movie from getting paused at item end. A very simplistic, and not gapless, looped playback.
     */
    _player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    _notificationToken = [[NSNotificationCenter defaultCenter] addObserverForName:AVPlayerItemDidPlayToEndTimeNotification object:item queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        // Simple item playback rewind.
        [[_player currentItem] seekToTime:kCMTimeZero];
    }];
}

Dans votre méthode viewWillDisappear :

if (_notificationToken) {
        [[NSNotificationCenter defaultCenter] removeObserver:_notificationToken name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
        _notificationToken = nil;
    }

Dans la déclaration de l'interface de votre contrôleur de vue dans le fichier d'implémentation :

id _notificationToken;

Vous voulez le voir fonctionner avant d'essayer ? Téléchargez et exécutez cet exemple d'application :

https://developer.apple.com/library/prerelease/ios/samplecode/AVBasicVideoOutput/Listings/AVBasicVideoOutput_APLViewController_m.html#//apple_ref/doc/uid/DTS40013109-AVBasicVideoOutput_APLViewController_m-DontLinkElementID_8

Dans mon application, qui utilise ce même code, il n'y a aucune pause entre la fin de la vidéo et le début. En fait, selon la vidéo, il n'y a aucun moyen pour moi de savoir que la vidéo est à nouveau au début, sauf l'affichage du timecode.

0voto

Shuju Dong Points 1

Vous pouvez ajouter un observateur AVPlayerItemDidPlayToEndTimeNotification et rejouer la vidéo. à partir du début du sélecteur, code comme ci-dessous

 //add observer
[[NSNotificationCenter defaultCenter] addObserver:self                                                 selector:@selector(playbackFinished:)                                                     name:AVPlayerItemDidPlayToEndTimeNotification
object:_aniPlayer.currentItem];

-(void)playbackFinished:(NSNotification *)notification{
    [_aniPlayer seekToTime:CMTimeMake(0, 1)];//replay from start
    [_aniPlayer play];
}

0voto

Victor John Points 332

Ce que j'ai fait est de le faire jouer en boucle, comme mon code ci-dessous :

[player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0)
queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
    float current = CMTimeGetSeconds(time);
    float total = CMTimeGetSeconds([playerItem duration]);
    if (current >= total) {
        [[self.player currentItem] seekToTime:kCMTimeZero];
        [self.player play];
    }
}];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X