有时AVPlayer停止并且seekToTime:没有响应

时间:2016-06-09 15:13:37

标签: ios objective-c avplayer

我正在使用AVPlayer播放youtube视频,如下所示,

    - (void)startYoutubeVideoAtUrl:(NSURL *)videoUrl
{
    NSLog(@"start player at url : %@", videoUrl);

    [HCYoutubeParser h264videosWithYoutubeURL:videoUrl completeBlock:^(NSDictionary *videoDictionary, NSError *error) {
        if (videoDictionary && videoDictionary.count > 0) {
            NSString *URLString = [self chooseYoutubeUrlFromUrlList:videoDictionary];

            AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[self videoURLWithCustomScheme:@"streaming" uRLString:URLString] options:nil];

            [asset.resourceLoader setDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

            pendingRequests = [NSMutableArray array];

            avPlayerItem = [AVPlayerItem playerItemWithAsset:asset];

            [self startVideoPlayBack];
        }
        else {
            [_delegate failedStartPalyInlineVideo];
        }
    }];
    }


-(void)startVideoPlayBack
{
    startTime = CFAbsoluteTimeGetCurrent();
    avPlayer = [[AVQueuePlayer alloc] initWithPlayerItem:avPlayerItem];
    avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
    [avPlayerItem addObserver:self forKeyPath:@"status" options:0 context:nil];
    [avPlayerLayer addObserver:self forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionNew context:nil];
    avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self.view.layer addSublayer:avPlayerLayer];

    [self watchApiCall];
    avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:[avPlayer currentItem]];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemPlaybackStalled:)
                                                 name:AVPlayerItemPlaybackStalledNotification
                                               object:[avPlayer currentItem]];


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    @try {
        if (!avPlayer) {
            return;
        }

        if (avPlayerItem.status == AVPlayerStatusReadyToPlay) {

        }
        else if (avPlayerItem.status == AVPlayerStatusFailed) {
            NSLog(@"----- AVPlayerStatusFailed ----");
            [self playbackVideo];
        }

        if (object == avPlayerLayer && [keyPath isEqualToString:@"readyForDisplay"]) {
            [self resetNetworkSpeedUsingLoadingTime];

            if (avPlayerLayer.readyForDisplay) {
                id<LoopingVideoDelegate> strongDelegate = self.delegate;

                if([strongDelegate readyForVideoDisplay]) {
                    [avPlayer play];
                }
                else {
                    [self removePlayer];
                }
            }
        }
    }
    @catch(NSException *ex) {
        NSLog(@"EXCEPTION : %@", ex);
    }
}

我的问题有时会导致视频停滞并触发AVPlayerItemPlaybackStalledNotification。此外,有时在调用[avPlayerItem seekToTime:kCMTimeZero];选择器之后,它没有响应AVPlayerItemDidPlayToEndTimeNotification。我无法找到解决方案。我查了一下,

[HCYoutubeParser thumbnailForYoutubeURL:videoUrl thumbnailSize:YouTubeThumbnailDefaultHighQuality completeBlock:^(UIImage *image, NSError *error) {

    if (!error) {
        [HCYoutubeParser h264videosWithYoutubeURL:videoUrl completeBlock:^(NSDictionary *videoDictionary, NSError *error) {
            NSString *URLString = [self chooseYoutubeUrlFromUrlList:videoDictionary];

            NSURL *urlToLoad = [NSURL URLWithString:URLString];

            avPlayerItem = [[AVPlayerItem alloc] initWithURL:urlToLoad];
            [self startVideoPlayBack];
        }];
    }
    else {
        NSLog(@"error in youtube parser");
    }
}];

并且没有任何玩家失误问题或seekToTime:没有回应问题。请帮忙。

1 个答案:

答案 0 :(得分:0)

观察您的AVPlayerItem's loadedTimeRangesseekableTimeRanges媒体资源,确保AVPlayer已加载可播放数据。在进行漫游时,AVPlayer经常会暂停不可播放(可以由AVPlayer)数据播放的数据。这应有助于进一步调查此问题。您也可以通过致电avPlayerItem.status == AVPlayerStatusReadyToPlay

上的play,在AVPlayer时尝试开始播放

来自AV Foundation编程指南

  

监控播放

     

您可以监控播放器的演示状态和正在播放的播放器项目的多个方面。这对于不受您直接控制的状态更改特别有用。例如:

     
      
  • 如果用户使用多任务切换到其他应用程序,则玩家的费率属性将降至0.0。

  •   
  • 如果您正在播放远程媒体,则播放器项的loadedTimeRanges和seekableTimeRanges属性将随着更多数据的变化而变化。

         

    这些属性告诉您玩家项目时间轴的哪些部分可用。

  •   
  • 当为HTTP直播流创建一个播放器项目时,玩家的currentItem属性会发生变化。

  •   
  • 播放HTTP直播时,播放器项的曲目属性可能会发生变化。   如果流为内容提供不同的编码,则可能发生这种情况;如果播放器切换到不同的编码,则曲目会改变。

  •   
  • 如果由于某种原因播放失败,播放器或播放器项的状态属性可能会更改。   您可以使用键值观察来监视对这些属性值的更改。

  •