Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 AVPlayerItems 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.

like image 577
Edelweiss Avatar asked Jun 22 '12 12:06

Edelweiss


2 Answers

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];
}
like image 157
darshansonde Avatar answered Oct 09 '22 02:10

darshansonde


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

  1. Create a queue that is an NSArray of AVPlayerItems.
  2. As each item is added to the queue, set up a NSNotificationCenter observer to wake up when the video reaches the end.
  3. 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.

like image 22
mpemburn Avatar answered Oct 09 '22 01:10

mpemburn