Fast switching between videos using AVFoundation

I’m writing an application where the user can record up to 6 video clips each with a duration of 2 seconds. When the video clips are recorded the user can play with them using 6 buttons – one for each clip. The user can then record a movie by switching between the 6 clips. The problem is that I need near instantaneous switching between the 6 clips when the user presses a button – otherwise the illusion of playing with the clips is lost – the functionality is somewhat similar to the app called CamBox in the App Store.

I first tried initializing every clip with and AVAsset in an AvPlayerItem in an AVPlayer every time the user pressed a button. The output of the player was directed at a an AVPlayerLayer in my main view. The problem is that the time it takes to load and start playing is quite long, meaning the the video lags when the user presses the buttons in rapid succession.

  • Change camera capture device while recording a video
  • MPNowPlayingInfoCenter nowPlayingInfo ignored for AVPlayer audio via AirPlay
  • Custom Camera zoom in/out while recording video using AVFoundation
  • iOS Swift: video thumbnail error
  • How can I extract an AVMetadataObject from a UIImage?
  • Cropping a captured image exactly to how it looks in AVCaptureVideoPreviewLayer
  • I the decided to try to preload all the clips using 5 AVPlayers and 5 AVPlayerLayers. The 5 PlayerLayers are inserted into my main view and when the user presses a button the currently playing AVPlayer is paused and rewound and the the currently visible AVPlayerLayer is hidden. The new AVPlayer is started and the corresponding AVPlayerLayer is shown. It works pretty ok being much faster than my first solution although not instantaneous but the problem is that I can only preload 4 clips meaning than when the user presses the button that play the last two the it lags big time. Below is my code to preload the clips

    -(void)loadVideos
    {
      layers = [[NSMutableArray alloc] initWithCapacity:6];
      players = [[NSMutableArray alloc] initWithCapacity:6];
    
      for(int i = 1; i < 7; i++)
      {
          NSURL* fileURL = [NSURL fileURLWithPath:[self getFileName:i]];        
          AVPlayerItem* avPlayerItem = [[[AVPlayerItem alloc] initWithURL:fileURL] autorelease];
          [avPlayerItem addObserver:self forKeyPath:@"status" options:0 context:nil];   
    
          AVPlayer *avPlayer = [[[AVPlayer alloc] initWithPlayerItem:avPlayerItem] autorelease];
    
          [avPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];   
          [avPlayer addObserver:self forKeyPath:@"currentItem" options:0 context:nil];   
          AVPlayerLayer* layer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
          layer.frame = self.playerView.bounds;
          [playerView.layer addSublayer:layer];
          [layers addObject:layer];
          [players addObject:avPlayer];
          layer.hidden = YES;
      }    
    }
    

    The event handler for the 6 buttons looks like this:

    - (IBAction)takeBtnClicked:(id)sender {
    int tag = ((UIButton*)sender).tag;
    AVPlayer* player;
    AVPlayerLayer* layer;
    if (layerIndex > -1) {
        player = [players objectAtIndex:layerIndex];
        layer = [layers objectAtIndex:layerIndex];
        [player pause];
        layer.hidden = YES;
        [player seekToTime:kCMTimeZero];
    }
    layerIndex = tag-1;
    player = [players objectAtIndex:layerIndex];
    layer = [layers objectAtIndex:layerIndex];
    [player play];
    layer.hidden = NO;    
    }
    

    I’m prette sure that the limitation of 4 preloaded video clips is a hardware limitation, but what is the alternative. Does anybody have any ideas?
    Thanks in advance.

    Solutions Collect From Internet About “Fast switching between videos using AVFoundation”

    See my answer for iphone-smooth-transition-from-one-video-to-another, it shows a library you can use to implement this logic and an example app with 3 buttons that kick off animated clips. Each clip also has an associated sound effect.