Replay items in AVQueuePlayer after last

I need to create something like an infinite loop in my AVQueuePlayer . Especially, I want to replay the whole NSArray of AVPlayerItem s once the last component finishes playing.

I must admit that I actually do not have any idea how to achieve this and hope you can give me some clues.


This is it pretty much from scratch. The components are:

  • Create a queue that is an NSArray of AVPlayerItems.
  • As each item is added to the queue, set up a NSNotificationCenter observer to wake up when the video reaches the end.
  • In the observer's selector, tell the AVPlayerItem that you want to loop to go back the the beginning, then tell the player to play.
  • (NOTE: The AVPlayerDemoPlaybackView comes from the Apple "AVPlayerDemo" sample. Simply a subclass of UIView with a setter)

    BOOL videoShouldLoop = YES;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSMutableArray *videoQueue = [[NSMutableArray alloc] init];
    AVQueuePlayer *mPlayer;
    AVPlayerDemoPlaybackView *mPlaybackView;
    
    // You'll need to get an array of the files you want to queue as NSARrray *fileList:
    for (NSString *videoPath in fileList) {
        // Add all files to the queue as AVPlayerItems
        if ([fileManager fileExistsAtPath: videoPath]) {
            NSURL *videoURL = [NSURL fileURLWithPath: videoPath];
            AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL: videoURL];
            // Setup the observer
            [[NSNotificationCenter defaultCenter] addObserver: self
                                                     selector: @selector(playerItemDidReachEnd:)
                                                         name: AVPlayerItemDidPlayToEndTimeNotification
                                                       object: playerItem];
            // Add the playerItem to the queue
            [videoQueue addObject: playerItem];
        }
    }
    // Add the queue array to the AVQueuePlayer
    mPlayer = [AVQueuePlayer queuePlayerWithItems: videoQueue];
    // Add the player to the view
    [mPlaybackView setPlayer: mPlayer];
    // If you should only have one video, this allows it to stop at the end instead of blanking the display
    if ([[mPlayer items] count] == 1) {
        mPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    }
    // Start playing
    [mPlayer play];
    
    
    - (void) playerItemDidReachEnd: (NSNotification *)notification
    {
        // Loop the video
        if (videoShouldLoop) {
            // Get the current item
            AVPlayerItem *playerItem = [mPlayer currentItem];
            // Set it back to the beginning
            [playerItem seekToTime: kCMTimeZero];
            // Tell the player to do nothing when it reaches the end of the video
            //  -- It will come back to this method when it's done
            mPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
            // Play it again, Sam
            [mPlayer play];
        } else {
            mPlayer.actionAtItemEnd = AVPlayerActionAtItemEndAdvance;
        }
    }
    

    That's it! Let me know of something needs further explanation.


    best way to loop a sequence of videos in AVQueuePlayer.

    observe for each playeritem in AVQueuePlayer.

    queuePlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    for(AVPlayerItem *item in items) {
        [[NSNotificationCenter defaultCenter] addObserver:self 
                selector:@selector(nextVideo:) 
                name:AVPlayerItemDidPlayToEndTimeNotification 
                object:item ];
    }
    

    on each nextVideo insert the currentItem again to queue it for playback. make sure to seek to zero for each item. after advanceToNextItem the AVQueuePlayer will remove the currentItem from queue.

    -(void) nextVideo:(NSNotification*)notif {
        AVPlayerItem *currItem = notif.userInfo[@"object"];
        [currItem seekToTime:kCMTimeZero];
        [queuePlayer advanceToNextItem];
        [queuePlayer insertItem:currItem afterItem:nil];
    }
    

    I figured out a solution to loop over all the videos in my video queue, not just one. First I initialized my AVQueuePlayer :

    - (void)viewDidLoad
    {
        NSMutableArray *vidItems = [[NSMutableArray alloc] init];
        for (int i = 0; i < 5; i++)
        {
            // create file name and make path
            NSString *fileName = [NSString stringWithFormat:@"intro%i", i];
            NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mov"];
            NSURL *movieUrl = [NSURL fileURLWithPath:path];
            // load url as player item
            AVPlayerItem *item = [AVPlayerItem playerItemWithURL:movieUrl];
            // observe when this item ends
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(playerItemDidReachEnd:)
                                                         name:AVPlayerItemDidPlayToEndTimeNotification
                                                       object:item];
            // add to array
            [vidItems addObject:item];
    
    
        }
        // initialize avqueueplayer
        _moviePlayer = [AVQueuePlayer queuePlayerWithItems:vidItems];
        _moviePlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    
        // create layer for viewing
        AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:_moviePlayer];
    
        layer.frame = self.view.bounds;
        layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        // add layer to uiview container
        [_movieViewContainer.layer addSublayer:layer];
    }
    

    When the notification is posted

    - (void)playerItemDidReachEnd:(NSNotification *)notification {
        AVPlayerItem *p = [notification object];
    
        // keep playing the queue
        [_moviePlayer advanceToNextItem];
        // if this is the last item in the queue, add the videos back in
        if (_moviePlayer.items.count == 1)
        {
            // it'd be more efficient to make this a method being we're using it a second time
            for (int i = 0; i < 5; i++)
            {
                NSString *fileName = [NSString stringWithFormat:@"intro%i", i];
                NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mov"];
                NSURL *movieUrl = [NSURL fileURLWithPath:path];
    
                AVPlayerItem *item = [AVPlayerItem playerItemWithURL:movieUrl];
    
                [[NSNotificationCenter defaultCenter] addObserver:self
                                                         selector:@selector(playerItemDidReachEnd:)
                                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                                           object:item];
    
                 // the difference from last time, we're adding the new item after the last item in our player to maintain the order
                [_moviePlayer insertItem:item afterItem:[[_moviePlayer items] lastObject]];
            }
        }
    }
    
    链接地址: http://www.djcxy.com/p/60750.html

    上一篇: 如何在php中生成一个唯一的会话ID

    下一篇: 最后一次在AVQueuePlayer中重播项目