Maintaining good scroll performance when using AVPlayer

后端 未结 6 1080
无人及你
无人及你 2020-11-30 17:34

I\'m working on an application where there is a collection view, and cells of the collection view can contain video. Right now I\'m displaying the video using AVPlayer

6条回答
  •  执笔经年
    2020-11-30 18:22

    I manage to create a horizontal feed like view with avplayer in each cell did it like so:

    1. Buffering - create a manager so you can preload (buffer) the videos. The amount of AVPlayers you want to buffer depends on the experience you are looking for. In my app i manage only 3 AVPlayers, so one player is being played now and the previous & next players are being buffered. All the buffering manager is doing is managing that the correct video is being buffered at any given point

    2. Reused cells - Let the TableView / CollectionView reuse the cells in cellForRowAtIndexPath: all you have to do is after you dequqe the cell pass him it's correct player (i just give the buffering an indexPath on the cell and he returns the correct one)

    3. AVPlayer KVO's - Every time the buffering manager gets a call to load a new video to buffer the AVPlayer create all of his assets and notifications, just call them like so:

    // player

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        self.videoContainer.playerLayer.player = self.videoPlayer;
        self.asset = [AVURLAsset assetWithURL:[NSURL URLWithString:self.videoUrl]];
        NSString *tracksKey = @"tracks";
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.asset loadValuesAsynchronouslyForKeys:@[tracksKey]
                                      completionHandler:^{                         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
                                              NSError *error;
                                              AVKeyValueStatus status = [self.asset statusOfValueForKey:tracksKey error:&error];
    
                                              if (status == AVKeyValueStatusLoaded) {
                                                  self.playerItem = [AVPlayerItem playerItemWithAsset:self.asset];
                                                  // add the notification on the video
                                                  // set notification that we need to get on run time on the player & items
                                                  // a notification if the current item state has changed
                                                  [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:contextItemStatus];
                                                  // a notification if the playing item has not yet started to buffer
                                                  [self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:contextPlaybackBufferEmpty];
                                                  // a notification if the playing item has fully buffered
                                                  [self.playerItem addObserver:self forKeyPath:@"playbackBufferFull" options:NSKeyValueObservingOptionNew context:contextPlaybackBufferFull];
                                                  // a notification if the playing item is likely to keep up with the current buffering rate
                                                  [self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:contextPlaybackLikelyToKeepUp];
                                                  // a notification to get information about the duration of the playing item
                                                  [self.playerItem addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:contextDurationUpdate];
                                                  // a notificaiton to get information when the video has finished playing
                                                  [NotificationCenter addObserver:self selector:@selector(itemDidFinishedPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
                                                  self.didRegisterWhenLoad = YES;
    
                                                  self.videoPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];
    
                                                  // a notification if the player has chenge it's rate (play/pause)
                                                  [self.videoPlayer addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:contextRateDidChange];
                                                  // a notification to get the buffering rate on the current playing item
                                                  [self.videoPlayer addObserver:self forKeyPath:@"currentItem.loadedTimeRanges" options:NSKeyValueObservingOptionNew context:contextTimeRanges];
                                              }
                                          });
                                      }];
        });
    });
    

    where: videoContainer - is the view you want to add the player to

    Let me know if you need any help or more explanations

    Good luck :)

提交回复
热议问题