1. Implement SHBQueuePlayer third party class
you can download from github:
https://github.com/jiutianhuanpei/SHBQueuePlayer
2. Implement AVPlayerViewController class
3. The below function is used for set urls for play video.
- (void)setUrls:(NSMutableArray *)urls index:(NSInteger)index
{
[_playedUrls removeAllObjects];
[_nextUrls removeAllObjects];
if (urls.count == 0 || urls == nil) {
[_qPlayer removeAllItems];
return;
}
if (index > urls.count) {
index = urls.count;
}
[_playedUrls addObjectsFromArray:[urls subarrayWithRange:NSMakeRange(0, index)]];
[_nextUrls addObjectsFromArray:[urls subarrayWithRange:NSMakeRange(index, urls.count - index)]];
[_qPlayer removeAllItems];
_arrCurrVideos = [NSMutableArray arrayWithArray:urls];
[self createMutableCompositionWithUrls:urls];
}
4. Implement AVMutableComposition for adding the videos one after another to resolve the black screen between two videos in Play All.
// avset ---> avplateritem ----> avplayer
-(void)createMutableCompositionWithUrls:(NSMutableArray *)urls
{
if (playerTimer)
[playerTimer invalidate];
if (mixComposition) {
mixComposition = nil;
videoTrack = nil;
audioTrack = nil;
}
mixComposition = [[AVMutableComposition alloc] init];
videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
arrVideoDurations = [[NSMutableArray alloc]init];
insertTime = kCMTimeZero;
for (id object in urls)
{
NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey:@YES};
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:object options:options];
AVAssetTrack *videoAsset = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.timeRange.duration);
[videoTrack insertTimeRange:timeRange
ofTrack:videoAsset
atTime:insertTime
error:nil];
[audioTrack insertTimeRange:timeRange
ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]
atTime:insertTime
error:nil];
insertTime = CMTimeAdd(insertTime,asset.duration);
[arrVideoDurations addObject:[NSString stringWithFormat:@"%f",CMTimeGetSeconds(insertTime)]];
}
// CMTime videoDuration;
videoComposition = [[AVPlayerItem alloc] initWithAsset:mixComposition];
if (_qPlayer.items > 0)
{
[_qPlayer replaceCurrentItemWithPlayerItem:videoComposition];
}
else
{
if ([_qPlayer canInsertItem:videoComposition afterItem:nil])
{
[_qPlayer insertItem:videoComposition afterItem:nil];
}
}
if (_currMovieTime.value != 0)
{
[videoComposition seekToTime:_currMovieTime];
[self showIntialLabel];
}
else
{
currIndex = 0;
}
[self play];
dispatch_async(dispatch_get_main_queue(), ^{
[self resetTimer];
});
}
//
//updateVideoLabel - This is for update information which is display on custom view where we play video
-(void)updateVideoLabel
{
if (_isPlaying == true) {
// NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
// numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
NSLog(@"Value of currIndex %d",currIndex);
NSLog(@"Total values is array: %lu",(unsigned long)arrVideoDurations.count);
float value;
if(currIndex value)
{
NSLog(@"Label changed");
dispatch_async(dispatch_get_main_queue(), ^{
if ([_delegate respondsToSelector:@selector(queuePlayerEndPlayed:)])
{
if (isRestarted) {
[_delegate queuePlayerEndPlayed:0];
isRestarted = false;
}
else
{
currIndex++;
[_delegate queuePlayerEndPlayed:currIndex];
}
NSLog(@"Label changed in movie ***** updateVideoLabel *******");
}
});
}
}
NSLog(@"Current video start time: %f Player time value: %f",value,CMTimeGetSeconds(videoComposition.currentTime));
}
}
//playerItemDidEndPlay - called when one movie gets play Completed
- (void)playerItemDidEndPlay:(NSNotification *)tifi {
_isPlaying = false;
NSLog(@"Player did complete movie");
if ([ServerConnection sharedConnection].isPlaying) {
[self stopTimer];
_currMovieTime = kCMTimeZero;
currIndex = 0;
isRestarted = YES;
if ([_delegate respondsToSelector:@selector(queuePlayerEndPlayed:)])
{
NSLog(@"Label changed in movie ***** playerItemDidEndPlay*******");
[_delegate queuePlayerEndPlayed:0];
}
if (_arrCurrVideos.count %f",CMTimeGetSeconds(videoComposition.currentTime));
[self play];
});
}
}
}
// Show Initial Label
-(void)showIntialLabel
{
int currVideo = 0;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
// @try {
for (int i = 0; i < arrVideoDurations.count; i++) {
if(currVideo value)
{
if ([_delegate respondsToSelector:@selector(queuePlayerEndPlayed:)])
{
NSLog(@"Label changed in movie ***** showIntialLabel *******");
[_delegate queuePlayerEndPlayed:currVideo];
return;
}
currVideo++;
}
}
}
}
//reset Timer
-(void)resetTimer
{
//for changing video players
playerTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(updateVideoLabel)
userInfo:nil
repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:playerTimer forMode:NSDefaultRunLoopMode];
}
//Stop Timer
-(void)stopTimer
{
if (playerTimer) {
[playerTimer invalidate];
}
}