13

I am working on a video application that plays a number of videos one after another. The videos are stored in an array of AVPlayerItems. AVQueuePlayer is initialized with those AVPlayerItems and it automatically plays the videos from that array.

The issue is when it changes to play the next video it gets stuck for a fraction of a second or it creates a jerk at the time it transitions from one to another. I want to improve this transition with some kind of animation such as Fade In and Fade Out while the video is changed.

My code for AVQueuePlayer:

AVQueuePlayer *mediaPlayer = [[AVQueuePlayer alloc] initWithItems:arrPlayerItems];
playerLayer=[AVPlayerLayer playerLayerWithPlayer:mediaPlayer];
playerLayer.frame=self.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
playerLayer.needsDisplayOnBoundsChange = NO;
[self.layer addSublayer:playerLayer];
self.layer.needsDisplayOnBoundsChange = YES;

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(itemPlayEnded:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:[mediaPlayer currentItem]];

I tried to create a new layer at the time of the transition and animate the old layer by decreasing its opacity and increasing the opacity of the new layer (to create the desired fade in fade out effect), but it is not working as desired.

The code for the custom transition:

-(void)TransitionInVideos {
    if (roundf(CMTimeGetSeconds(mediaPlayer.currentTime))==roundf(CMTimeGetSeconds(mediaPlayer.currentItem.duration))) {
        [self.layer addSublayer:playerLayerTmp];

        //Animation for the transition between videos
        [self performSelector:@selector(FadeIn) withObject:nil afterDelay:0.3];
        [self performSelector:@selector(FadeOut) withObject:nil afterDelay:0.3];
    }
}

-(void)FadeIn {
    CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
    fadeAnim.toValue = [NSNumber numberWithFloat:0.0];
    fadeAnim.duration = 2.0;
    [playerLayer addAnimation:fadeAnim forKey:@"opacity"];
    [self performSelector:@selector(HideLayer) withObject:nil afterDelay:2.0];
}

-(void)FadeOut {
    CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeAnim.fromValue = [NSNumber numberWithFloat:0.0];
    fadeAnim.toValue = [NSNumber numberWithFloat:1.0];
    fadeAnim.duration = 1.0;
    [playerLayerTmp addAnimation:fadeAnim forKey:@"opacity"];
    [self performSelector:@selector(ShowLayer) withObject:nil afterDelay:1.0];
}

-(void)HideLayer {
    playerLayer.opacity=0.0;
}

-(void)ShowLayer {
    playerLayerTmp.opacity=1.0;
}

How can a transition be applied to videos in the AVQueuePlayer?

Jordan H
  • 52,571
  • 37
  • 201
  • 351
Parvez Belim
  • 1,003
  • 13
  • 36
  • I want that same If you found your solution then post here It will help others. – Anand Suthar Nov 15 '13 at 17:03
  • Apple gives sample code using the queue player w/ seamless transition if it helps: https://developer.apple.com/library/content/samplecode/avloopplayer/Introduction/Intro.html – iwasrobbed Nov 21 '17 at 17:23

3 Answers3

5

We can set the opacity for AVMutableVideoCompositionLayerInstruction that will be add to the video while exporting or AVPlayer as VideoComposition property and that will create the fade in and fade out effect.

 [layerInstruction setOpacityRampFromStartOpacity:1.0 toEndOpacity:0.0 timeRange:CMTimeRangeMake(CMTimeSubtract([mutableComposition duration], CMTimeMake(Transition_Time, 1)), [mutableComposition duration])];

 [layerInstruction setOpacityRampFromStartOpacity:0.0 toEndOpacity:1.0 timeRange:CMTimeRangeMake(kCMTimeZero, CMTimeMake(1, 1))];

this are the code for giving the effect.


More complete examples:

iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
Parvez Belim
  • 1,003
  • 13
  • 36
2

we had exactly the same problem in one of our app - and unfortunately, we had to drop the standard player and use logic from this example:

https://developer.apple.com/library/ios/samplecode/StitchedStreamPlayer/Listings/Classes_MyStreamingMovieViewController_m.html#//apple_ref/doc/uid/DTS40010092-Classes_MyStreamingMovieViewController_m-DontLinkElementID_8

hope that helps.

avs099
  • 10,937
  • 6
  • 60
  • 110
  • I gone through this sample code earlier.It just changes the video and in that also the black part gets appears for fraction of seconds.What I want is some kind of effects at the time of transition from one video to another video. Well thanks for showing interest and helping !!! – Parvez Belim Nov 15 '13 at 07:11
  • i know for sure that we had the same issue as you do - we had to play 2 videos - one after another. Using standard AvPlayer control - we got pause for a fraction of second, and/or black flickering. Using the technique from the article above helped us to solve this - now 2 videos are played like it's a single one. I will try to get more insight from our team on what exactly was done. – avs099 Nov 15 '13 at 14:23
2

I was able to achieve the desired effect by using two separate AVPlayer objects playing back to back. The players are using different views to play on.

The idea is to fade in the second video player's view before the first video is going to finish.

The demo project can be found here: IHLoopingVideoPlayerView

It loops the same video over and over but the same idea can be applied to any number of videos.

Ishan Handa
  • 2,271
  • 20
  • 25
  • @iwasrobbed FYI that link requires a login. Those of us who aren't in that slack channel can't access it. – RonLugge Nov 20 '17 at 21:31
  • @RonLugge Apologies for that, here's sample code from Apple: https://developer.apple.com/library/content/samplecode/avloopplayer/Introduction/Intro.html – iwasrobbed Nov 21 '17 at 17:22
  • this was a good solution! I had to refactor it a bit for my purposes, but all in all you saved me a lot of time. Thank you! – horseshoe7 Apr 27 '23 at 10:08