Zrobiłem proste demo dla Ciebie i innych, którzy chcą skrócić czas buforowania każdego filmu z adresu URL.
UWAGA: Nie wiem, to jest właściwa droga, czy nie, ale to praca idealna dla mnie bez problemu. Jeśli ktoś wie więcej lub chce poprawić kod w celu uzyskania lepszych wyników, zapraszamy do zmiany odpowiedzi.
W poniższym kodzie Pierwsze wideo wykonuje normalny czas buforowania. Następny film rozpocznie się automatycznie po zakończeniu bieżącego wideo i możesz przesuwać palcem w lewo lub w prawo, aby przejść do następnego i poprzedniego wideo.
Wykonaj poniższe czynności.
1) W pliku wideoPlayerVC.h.
#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>
@interface videoPlayerVC : UIViewController
{
AVPlayerViewController *avPlyrViewController;
AVPlayerItem *currentAVPlyrItem;
int currentVideoNO; // For current video track.
NSMutableArray *arrOfAVPItems;
NSMutableArray *arrOfPlyer;
}
2) W videoPlayerVC.m pliku
Tutaj można rozpocząć odtwarzanie wideo przez kliknięcie przycisku. Poniżej znajduje się metoda działania przycisku.
-(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
}];
}
Teraz wpisz kod metody playVideos
.
#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
}
}
Obserwator powiadomień o zakończeniu wideo.
- (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.
}
Metoda Play Następny wideo
-(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];
}
metoda odtwarzania poprzedniego filmu.
-(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];
}
Wykonaj następujące kroki. W razie wątpliwości prosimy o komentarz.
Ładowanie elementu AVPlayerItem nie powoduje opóźnień odtwarzacza; jeśli się nie zgadzasz pokaż mi kod, który to udowodni. Mam działającą aplikację, która ładuje jeden plik AVPlayerItem dla każdego zasobu wideo na telefonie iPhone w jednej komórce widoku kolekcji. Możesz przewijać tak szybko, jak chcesz, a pierwsza klatka każdego filmu będzie wyświetlana tak, jakbyś prosił tylko o pojedynczy obraz z zasobu. Jednak opóźnienie odtwarzania wydaje się WYŁĄCZNIE, jeśli zaczyna się podczas przewijania. To dlatego, że umieszczasz zbyt wiele rzeczy w jednym wątku i jednej kolejce. Rozpocznij odtwarzanie w oddzielnym wątku i kolejce, a opóźnienie zniknie. –