【问题标题】:iOS objective c How to load next coming video while playing current video without delayiOS目标c如何在无延迟播放当前视频的同时加载下一个视频
【发布时间】:2017-03-06 20:37:04
【问题描述】:

在我的应用程序中,ai 已将所有视频 url 加载到 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];
    }
}

这里播放器玩得很好,但延迟很小。 .如何在无延迟播放当前视频的同时加载下一个视频。

【问题讨论】:

    标签: ios objective-c avplayer


    【解决方案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];
    

    【讨论】:

    • 嗨 Goz,我是 AVPlayer 的新手,请给我一个例子。
    • 嗨 Goz,你已经初始化了 pAVComposition 并且没有在上面的代码中使用。 .并使用 pComposition 初始化了一个播放器项目,我已经添加了,请您详细帮助我。
    • 由于未捕获的异常 'NSInvalidArgumentException' 导致错误终止应用程序,原因:'-[AVPlayerItem trackingWithMediaType:]: unrecognized selector sent to instance 0x60000001a2e0'
    • 是的,对不起。 pAVComposition 应该是 pComposition。
    【解决方案2】:

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

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

    【讨论】:

    • 好的兄弟我会尽力让你知道的。 . .
    • AVQueuePlayer 不缓冲视频项。
    • 您也无法使用 AVQueuePlayer 正确地向后和向前搜索 ...
    猜你喜欢
    • 2014-01-08
    • 1970-01-01
    • 2019-11-18
    • 2020-04-08
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    相关资源
    最近更新 更多