3

我在 UITableView 中有多个视频。我想做一些像vine's feeds之类的东西。滚动到视频时自动播放视频。
我使用 AVPlyer 来做到这一点。但我发现当两个视频切换时它不是那么流畅。
任何人都可以提供一些建议吗?

这是我的 tableViewController 的 observeValueForKeyPath,我用它来做视频切换;

[oldCell cleanupMoviePlayer] 将做一些清洁工作(为了清洁视图移除一些观察者)

[(MOVideoPlayer_AVPlayer*)newItem startPlay] 将进行一些初始化和设置(设置 AVPlayerItem 并播放)

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{


    id newItem = [change objectForKey:NSKeyValueChangeNewKey];
    id oldCell = [change objectForKey:NSKeyValueChangeOldKey];
    if (oldCell == (id)[NSNull null]) {

    } else if([oldCell isKindOfClass:[MOVideoPlayer_AVPlayer class]]) {
        [oldCell cleanupMoviePlayer];

    }

    if ([newItem isKindOfClass:[MOVideoPlayer_AVPlayer class]]) {
        [(MOVideoPlayer_AVPlayer*)newItem startPlay];
    }


}

-(void) startPlay
{    
    willStartePlay = YES;

    double delayInSeconds = 0.5;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        [self.indicator startAnimating];

        if (isClearnup) {
            return;
        }

        NSString *videoFilePath =[NSString stringWithFormat:@"%@%@",NSTemporaryDirectory(),[self.post.video_url lastPathComponent]];
        //NSLog(@"the videoFilePath is %@",videoFilePath);

            NSFileManager *fileManager = [NSFileManager defaultManager];
            if (![fileManager fileExistsAtPath:videoFilePath]) {
                NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.post.video_url]];
                NSLog(@"post.video_url:%@",self.post.video_url);
                downloadOperation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:videoFilePath shouldResume:NO];
                [downloadOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

                    if ([fileManager fileExistsAtPath:videoFilePath]) {
                        [self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
                    }


                } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                    NSLog(@"the error is %@",error);
                    NSLog(@"%@",operation.description);
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.indicator stopAnimating];

            });
            }];
                [downloadOperation start];

            } else {

                [self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
            }


    });



}



-(void)createAndPlayMovieForURL:(NSURL *)movieURL sourceType:(MPMovieSourceType)sourceType
{

    if (isClearnup) {
        return;
    }

    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:movieURL options:nil];
    NSArray *requestedKeys = [NSArray arrayWithObjects: kPlayableKey, nil];
    [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self prepareToPlayAsset:asset withKeys:requestedKeys];
        });
    }];


}


-(void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
{


    if (isClearnup) {
        return;
    }

    for (NSString *thisKey in requestedKeys)
    {
        NSError *error = nil;
        AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
        if (keyStatus == AVKeyValueStatusFailed)
        {

            return;
        }

    }

    if (!asset.playable) {
        return;
    }

    if (self.currentPlayerItem) {
        [self.currentPlayerItem removeObserver:self forKeyPath:kStatusKey context:MOAVPlayerStatusObservationContext];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.currentPlayerItem];
    }


    self.currentPlayerItem = [AVPlayerItem playerItemWithAsset:asset];
    [self.currentPlayerItem addObserver:self
                             forKeyPath:kStatusKey
                                options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                                context:MOAVPlayerStatusObservationContext];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:self.currentPlayerItem];


    if (!self.player) {
        self.player = [AVPlayer playerWithPlayerItem:self.currentPlayerItem];


        [self.player addObserver:self
                       forKeyPath:kCurrentItemKey
                          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                          context:MOAVPlayerCurrentItemObservationContext];



        /* Observe the AVPlayer "rate" property to update the scrubber control. */
        [self.player addObserver:self
                       forKeyPath:kRateKey
                          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                          context:MOAVPlayerRateObservationContext];


    } 

    if (self.player.currentItem != self.currentPlayerItem) {
        [self.player replaceCurrentItemWithPlayerItem:self.currentPlayerItem];

    }



}


-(void)playerItemDidReachEnd:(NSNotification*)notication
{
    [self.player seekToTime:kCMTimeZero];
    [self.player play];
}


-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{

    if (context == MOAVPlayerStatusObservationContext) {

        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status) {
            case AVPlayerStatusUnknown:
            {
                //NSLog(@"AVPlayerStatusUnknown");
            }

                break;
            case AVPlayerStatusReadyToPlay:
            {
                NSLog(@"AVPlayerStatusReadyToPlay");
                [self.player play];
            }
                break;
            case AVPlayerStatusFailed:
            {
                //NSLog(@"AVPlayerStatusFailed");
            }
                break;
        }
    } else if (context == MOAVPlayerRateObservationContext) {

        //NSLog(@"MOAVPlayerRateObservationContext");

    } else if (context == MOAVPlayerCurrentItemObservationContext){

       // NSLog(@"CurrentItem change");
        AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];

        if(newPlayerItem == (id)[NSNull null]){
            // newPlayeritem is null?
            //NSLog(@"newPlayerItem IS null");

        } else {


            //self.playerView.frame = self.backgroundImageView.frame;

            //[self addSubview:self.playerView];

            if (isClearnup) {
                return;
            }

            isStartePlay = YES;

            double delayInSeconds = 0.2;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                //self.playerView.player = self.player;
                [self.indicator stopAnimating];
                //[self.playerView setVideoFillMode:AVLayerVideoGravityResizeAspect];
                //dispatch_async(dispatch_get_main_queue(), ^{
                  //  [self.player play];
                    self.playerView.player = self.player;
                //});
                //

            });




        }

    }  else {

        [super observeValueForKeyPath:keyPath  ofObject:object change:change context:context];
    }



}


-(void)cleanupMoviePlayerView
{

    //[self.playerView removeFromSuperview];
    self.playerView.player = nil;
    //[self.moviePlayer.view removeFromSuperview];
    //[self.maskView removeFromSuperview];
}

-(void)handleTap:(UITapGestureRecognizer*)tapGestureRecognizer;
{

    if (interrupted) {
        return;
    }
   // NSLog(@"tapGestureRecognizer");
    if (isplaying) {
        [self.moviePlayer pause];
    } else {
        [self.moviePlayer play];
    }



}

// Remove the movie notification observers from the movie object.
-(void)removeMovieNotificationHandlers
{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

    }


-(void) cleanupMoviePlayer
{

    if (willStartePlay && isStartePlay) {
        [self.player seekToTime:kCMTimeZero];
        //[self.moviePlayer stop];
        [self cleanupMoviePlayerView];
        [self removeMovieNotificationHandlers];
    }

    isClearnup = YES;


}

-(void)prepareForReuse
{
    willStartePlay = isStartePlay = isClearnup = NO;
}

4

0 回答 0