Pre-buffering for AVQueuePlayer

前端 未结 6 2063
-上瘾入骨i
-上瘾入骨i 2020-11-28 04:23

Does anyone know if AVQueuePlayer starts buffering the next AVPlayerItem when the current item is about to finish playing?

I know there\'s

6条回答
  •  鱼传尺愫
    2020-11-28 04:30

    I made simple demo for you and others that want to reduce buffering time of each video from URL.

    NOTE: Don't know this is right way or not but It's working perfect for me without any issue. If anyone know more or want to improve code for better result then welcome to change my answer.

    In the below code, First video take normal buffering time. Next video will be start automatically when current video is finish and you can swipe left and right to move next and previous video.

    Follow the below steps.

    1) In the videoPlayerVC.h file.

    #import 
    #import 
    
    @interface videoPlayerVC : UIViewController
    {
        AVPlayerViewController *avPlyrViewController;
        AVPlayerItem *currentAVPlyrItem;
    
        int currentVideoNO;  // For current video track.
        NSMutableArray *arrOfAVPItems;
        NSMutableArray *arrOfPlyer;
    }
    

    2) In the videoPlayerVC.m file

    Here you can start to play video by click on button. Below is button's action method.

    -(void)clickOnPlayVideosImage:(UIButton *)sender
    {
       // In my App. all video URLs is up to 15 second.
        currentVideoNO = 0;
        NSMutableArray *arrForVideoURL = [[NSMutableArray alloc]initWithObjects:
                                          [NSURL URLWithString:@"http://videos/url1.mov"],
                                          [NSURL URLWithString:@"http://videos/url2.mov"],
                                          [NSURL URLWithString:@"http://videos/url3.mov"],
                                          [NSURL URLWithString:@"http://videos/url3.mov"],
                                          [NSURL URLWithString:@"http://videos/url4.mov"],
                                          [NSURL URLWithString:@"http://videos/url5.mov"], nil];
    
        AVPlayerItem *thePlayerItemA = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:0]];
        AVPlayerItem *thePlayerItemB = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:1]];
        AVPlayerItem *thePlayerItemC = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:2]];
        AVPlayerItem *thePlayerItemD = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:3]];
        AVPlayerItem *thePlayerItemE = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:4]];
        AVPlayerItem *thePlayerItemF = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:5]];
    
        if(arrOfAVPItems.count > 0)
           [arrOfAVPItems removeAllObjects];
        arrOfAVPItems = nil;
    
        if(arrOfPlyer.count > 0)
            [arrOfPlyer removeAllObjects];
        arrOfPlyer = nil;
        arrOfPlyer = [[NSMutableArray alloc] init];
    
        arrOfAVPItems = [NSMutableArray arrayWithObjects:thePlayerItemA, thePlayerItemB, thePlayerItemC, thePlayerItemD, thePlayerItemE, thePlayerItemF, nil]; // Add All items in the Array
    
        for(AVPlayerItem *myPlyrItem in arrOfAVPItems)
        {
            AVPlayer *videoPlayerNext = [AVPlayer playerWithPlayerItem:myPlyrItem]; /// Add item in the player
            [videoPlayerNext play]; 
            [videoPlayerNext pause];
            [arrOfPlyer addObject:videoPlayerNext]; /// Make Array of  "AVPlayer" just reduce buffering of each video. 
        }
    
        avPlyrViewController = [AVPlayerViewController new];
        avPlyrViewController.delegate = self;
        avPlyrViewController.player = (AVPlayer *)arrOfPlyer[0]; // Add first player from the Array.
        avPlyrViewController.showsPlaybackControls = YES;
        avPlyrViewController.allowsPictureInPicturePlayback = YES;
        avPlyrViewController.videoGravity = AVLayerVideoGravityResizeAspect;
    
        [self presentViewController:avPlyrViewController animated:YES completion:^{
            [self performSelector:@selector(playVideos) withObject:nil afterDelay:1];/// call method after one second for play video.
    
            UISwipeGestureRecognizer * swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeleftToNextVideo:)];
            swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
            [avPlyrViewController.view addGestureRecognizer:swipeleft]; // Add left swipe for move on next video
    
            UISwipeGestureRecognizer * swiperight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeleftToPerviousVideo:)];
            swiperight.direction=UISwipeGestureRecognizerDirectionRight;
            [avPlyrViewController.view addGestureRecognizer:swiperight]; // Add right swipe for move on previous video
        }];
    }
    

    Now write playVideos method code.

    #pragma mark - AVPlayer Methods -
    
    -(void)playVideos
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem]; // remove current "AVPlayerItem" from the notification observe.
    
        if(arrOfAVPItems.count > 0)
        {
            currentAVPlyrItem = (AVPlayerItem *)arrOfAVPItems[currentVideoNO]; // Add "AVPlayerItem" from the array.
    
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem]; // Add notification observer to indication current "AVPlayerItem" is finish.
    
            // pause and nil previous player if available.
            [avPlyrViewController.player pause];
            avPlyrViewController.player = nil;
    
            avPlyrViewController.player = (AVPlayer *)arrOfPlyer[currentVideoNO]; // add new player from the array
            [avPlyrViewController.player.currentItem seekToTime:kCMTimeZero]; // set for start video on initial position.
            [avPlyrViewController.player play]; // Play video
    
        }
    }
    

    Notification observer to indicate video is finish.

    - (void)playerItemDidReachEnd:(NSNotification *)notification
    {
        NSLog(@"IT REACHED THE END");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem];  // remove current "AVPlayerItem" from the notification observe.
    
        [self swipeleftToNextVideo:nil]; // Call method for next video.
    }
    

    Method for play next video

    -(void)swipeleftToNextVideo:(UISwipeGestureRecognizer*)gestureRecognizer
    {
        currentVideoNO++;
        if(currentVideoNO > (arrOfAVPItems.count -1))
            currentVideoNO = 0;
    
        NSLog(@"current - %d and last - %d", currentVideoNO, (int)(arrOfAVPItems.count -1));
    
        [self playVideos];
    }
    

    Method for play previous video.

    -(void)swipeleftToPerviousVideo:(UISwipeGestureRecognizer*)gestureRecognizer
    {
        currentVideoNO--;
        if(currentVideoNO < 0)
            currentVideoNO = (int)(arrOfAVPItems.count -1);
    
        NSLog(@"current - %d and last - %d", currentVideoNO, (int)(arrOfAVPItems.count -1));
    
        [self playVideos];
    }
    

    Follow these steps. If any doubt then comment please.

提交回复
热议问题