iOS目标c如何在无延迟播放当前视频的同时加载下一个即将播放的视频

时间:2017-03-01 09:20:41

标签: ios objective-c avplayer

在我的应用程序中,ai已将所有视频网址加载到AVPlayer,它有前一个和下一个按钮,我有设置播放器

    -(void)setUpMyNewPlayer
    {
            [self addTimer];
        NSURL *url=[NSURL URLWithString:_videosArray[0]];
        _currentIndex =0;
        videoPlayer = [[AVPlayer alloc]init]; //WithPlayerItem:_avPlayerItem];
        videoPlayer.automaticallyWaitsToMinimizeStalling = NO;
        AVAsset *asset = [AVAsset assetWithURL:url];
        [asset loadValuesAsynchronouslyForKeys:@[@"playable"] completionHandler:^{

            AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
            videoPlayer = [AVPlayer playerWithPlayerItem:item];
            AVPlayerLayer  *playerLayer = [AVPlayerLayer playerLayerWithPlayer:videoPlayer];
            playerLayer.videoGravity = AVLayerVideoGravityResize;
            playerLayer.frame = CGRectMake(0, 0, self.playView.frame.size.width, self.playView.frame.size.height);
            [self.playView.layer addSublayer:playerLayer];
            [videoPlayer play];
            CMTime interval = CMTimeMakeWithSeconds(0.5, NSEC_PER_SEC);
            dispatch_queue_t mainQueue = dispatch_get_main_queue();


            __weak typeof(self) weakSelf = self;
            [videoPlayer addPeriodicTimeObserverForInterval:interval
                                                      queue:mainQueue
                                                 usingBlock:^(CMTime time) {
                                                     // Use weak reference to self
                                                     if (_currentIndex==_contentImages.count-1) {
                                                         weakSelf.nextButton.hidden=YES;
                                                         weakSelf.previousButton.hidden=NO;
                                                     }
                                                     else if (_currentIndex==0)
                                                     {
                                                         weakSelf.previousButton.hidden=YES;
                                                         if (_contentImages.count>1) {
                                                             weakSelf.nextButton.hidden=NO;
                                                         }
                                                         else
                                                         {
                                                             weakSelf.nextButton.hidden=YES;
                                                         }

                                                     }
                                                     else if (_currentIndex>0 && _currentIndex!=_contentImages.count-1)
                                                     {
                                                         // NSLog(@"Showing Both");
                                                         weakSelf.nextButton.hidden=NO;
                                                         weakSelf.previousButton.hidden=NO;
                                                     }

                                                 }];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying1:) name:AVPlayerItemDidPlayToEndTimeNotification object:item];
        }];

    }

-(void)itemDidFinishPlaying1:(NSNotification *) notification {
   //  
    // Will be called when AVPlayer finishes playing playerItem
    if (_currentIndex == _videosArray.count-1) {

    }
    else{

        _currentIndex = _currentIndex+1;
        NSURL *url=[NSURL URLWithString:_videosArray[_currentIndex]];
        AVAsset *asset = [AVAsset assetWithURL:url];
        AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
        [videoPlayer replaceCurrentItemWithPlayerItem:item];
        [self changePage:UIPageViewControllerNavigationDirectionForward];
        [self addTimer];
    }

}


-(void)addTimer
{
    myTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self
                                             selector: @selector(callAfterOneSecond1:) userInfo: nil repeats: YES];
}

-(void) callAfterOneSecond1:(NSTimer*)t
{
    [[AppDelegate shared] showLoading];
    if (videoPlayer.rate !=0 && videoPlayer.error == nil && videoPlayer.status == AVPlayerStatusReadyToPlay) {
        [[AppDelegate shared]removeLoading];
        [myTimer invalidate];
        myTimer=nil;
    }

}

pragma mark- PreviousAction

- (IBAction)previousButtonAction:(id)sender {

    if (_currentIndex == 0) {

    }
    else{
        _currentIndex = _currentIndex-1;
        NSURL *url=[NSURL URLWithString:_videosArray[_currentIndex]];
        AVAsset *asset = [AVAsset assetWithURL:url];
        AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
        [videoPlayer replaceCurrentItemWithPlayerItem:item];
        [videoPlayer play];
        [self changePage:UIPageViewControllerNavigationDirectionReverse];
        [self addTimer];
    }
   }

pragma mark- NextAction

- (IBAction)nextButtonAction:(id)sender {  

    if (_currentIndex == _videosArray.count-1) {

    }
    else{
        _currentIndex = _currentIndex+1;
        NSURL *url=[NSURL URLWithString:_videosArray[_currentIndex]];
        AVAsset *asset = [AVAsset assetWithURL:url];
        AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
        [videoPlayer replaceCurrentItemWithPlayerItem:item];
        [videoPlayer play];
        [self changePage:UIPageViewControllerNavigationDirectionForward];
           [self addTimer];
    }
}

这里的球员打得很好,但延迟很小。 。如何在播放当前视频的同时加载下一个即将播放的视频。

2 个答案:

答案 0 :(得分:1)

我有点生疏,如果你想做任何稍微复杂的事情,整个AVFoundation的iOS文档都是不合适的。我这样做已经有一段时间了,但这样的事情应该有效(我假设你有一个NSArray*pAssets包含你所有的视频AVAsset*

// Define the composition.
AVMutableComposition*       pComposition        = [AVMutableComposition composition];

// Define the tracks in the composition.
AVMutableCompositionTrack*  pCompositionVideoTrack  = [pComposition addMutableTrackWithMediaType: AVMediaTypeVideo preferredTrackID: 1];
AVMutableCompositionTrack*  pCompositionAudioTrack  = [pComposition addMutableTrackWithMediaType: AVMediaTypeAudio preferredTrackID: 2];

CMTime time = kCMTimeZero;
for ( AVAsset* pAssetsAsset in pAssets )
{
    // Grab first video and audio tracks
    AVAssetTrack*   pAssetsAssetVideoTrack  = [pAssetsAsset tracksWithMediaType: AVMediaTypeVideo].firstObject;     
    AVAssetTrack*   pAssetsAssetAudioTrack  = [pAssetsAsset tracksWithMediaType: AVMediaTypeAudio].firstObject;

    // Get time range of entire video.
    CMTimeRange     timeRange   = CMTimeRangeMake( kCMTimeZero, timepAssetsAsset.duration );

    // Insert the entire video and audio into their respective tracks at "time".
    NSError*    pVideoError     = nil;
    NSError*    pAudioError     = nil;
    [pCompositionVideoTrack insertTimeRange: timeRange ofTrack: pAssetsAssetVideoTrack atTime: time error: &pVideoError];       
    [pCompositionAudioTrack insertTimeRange: timeRange ofTrack: pAssetsAssetAudioTrack atTime: time error: &pAudioError];

    // Move time along appropriately.
    time    = CMTimeAdd( time, pAssetsAsset.duration );
}

如果您然后传递AVMutableComposition来自AVAsset,那么您可以正常使用它并将其放入AVPlayer(通过AVPlayerItem)。

现在,您可以搜索视频中的任何一点。存储每个视频的开始/结束点,您可以轻松找到它。

编辑:它使用AVPlayer非常简单。首先,你需要创建一个AVPlayerItem ..然后你需要播放它。

AVPlayerItem*   pPlayerItem = [AVPlayerItem playerItemWithAsset: pComposition];
AVPlayer*   pPlayer     = [AVPlayer playerWithPlayerItem: pPlayerItem];

现在您需要将其附加到视图层。所以从你的ViewController里面做这样的事情:

AVPlayerLayer*  pLayer      = [AVPlayerLayer playerLayerWithPlayer: pPlayer];
[self.view.layer addSublayer: pLayer];

答案 1 :(得分:0)

使用AVQueuePlayer代替简单AVPlayer。在当前视频结束时,它将预加载下一个视频。

在此处查看如何使用AVQueuePlayerhttps://stackoverflow.com/a/22785665/1271424