【问题标题】:Handle streaming events with AVPlayer使用 AVPlayer 处理流事件
【发布时间】:2011-09-15 23:57:13
【问题描述】:

我正在构建一个播放音频流(来自网络广播)的应用程序。

我正在使用AVPlayer

  1. 我想知道当连接速度很慢或用户刚刚单击“播放”时,您将如何处理AVPlayer's“缓冲”。我想检测到AVPlayer 正在“缓冲”以显示UIActivityIndicatorView

  2. 在后台运行时出现同样的问题。这种情况下缓冲怎么办?

【问题讨论】:

    标签: ios xcode stream avfoundation avplayer


    【解决方案1】:

    我已经找到了解决这个问题的方法。

    if (self.avPlayer.currentItem.playbackLikelyToKeepUp == NO) 
    {
        // Show activity indicator
    }
    

    【讨论】:

    • 你用什么方法放的?
    • Ruben Martinez Jr - 使用计时器进行检查(1 秒最佳),在 KeepUp ==YES timer.invalidate()
    【解决方案2】:

    第一个问题

    这个话题可以参考我的回答ios avplayer trigger streaming is out of buffer

    第二次

    这是我解决同样问题的方法:

    在处理缓冲区空事件的地方添加以下代码:

        if (object == playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"])
        {
            if (playerItem.playbackBufferEmpty) {
                [[NSNotificationCenter defaultCenter] postNotificationName:@"message" object:@"Buffering..."];
                
                if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
                {
                    task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
                    }];
                }
            }
        }
    

    现在您必须在缓冲区准备好再次运行后停止此后台任务:

    if (object == playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    {
        if (playerItem.playbackLikelyToKeepUp)
        {
            [player play];
            
            if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
            {
                [[UIApplication sharedApplication] endBackgroundTask:task];
                task = 0;
            }
        }
    }
    

    ps:任务在我的 .h 文件中声明为 UIBackgroundTaskIdentifier task;

    【讨论】:

    • 这里为什么需要bg任务?我没有看到连接。
    • 发生这种情况是因为当您的应用程序处于后台并且由于某种原因您的流停止时,iOS 将终止您的播放器,并且一旦您再次开始接收流,您将无法继续。所以有了这个,我们可以在 iOS 上作弊,让它认为你的播放器还在工作。
    • 您的任务块中需要什么吗?还是仅仅为了让应用程序委托上的循环运行而存在?
    【解决方案3】:

    试试这个:

    AVPlayerItem* mPlayerItem;
    

    if(context == AVPlayerDemoPlaybackViewControllerCurrentItemBufferEmptyContext) 
    {
        if (object == self.mPlayerItem && [path isEqualToString:@"playbackBufferEmpty"]) 
        {
            if (self.mPlayerItem.playbackBufferEmpty)
            {
                playBufferEmpty = TRUE;
                [indicator startAnimating];
                [vidStreaminglabel setText:@"Buffering..."];
                [vidStreaminglabel setHidden:NO];
            }
        }
    }
    
    else if(context == AVPlayerDemoPlaybackViewControllerCurrentItemPlayBackBufferFullContext)
    {
        if (object == mPlayerItem && [path isEqualToString:@"playbackBufferFull"]){
            if (self.mPlayerItem.playbackBufferFull) {
                [mPlayer play];
            }
        }
    }
    
    else if (context == AVPlayerDemoPlaybackViewControllerCurrentItemPlayBackLikelyToKeepUpContext)
    {
        if (object == mPlayerItem && [path isEqualToString:@"playbackLikelyToKeepUp"])
        {
             if(self.mPlayerItem.playbackLikelyToKeepUp)
             {
                 // Autoplay after buffer 
                 if(!(mRestoreAfterScrubbingRate != 0.f || [self.mPlayer rate] != 0.f))
                 {
                     if (self.presentingViewController) {
                         [mPlayer play];
                     }
    
                     playBufferEmpty = FALSE;
                     [indicator stopAnimating];
                     [vidStreaminglabel setHidden:YES];
                 }
            }
        }
    }
    

    【讨论】:

    • 什么是上下文,它从何而来?您能否包括方法声明和/或调用?
    • 请给出正确的解释不要浪费别人的时间!!
    【解决方案4】:

    对于 Swift 3

    这对我来说很好,也许它可以帮助,在addPeriodicTimeObserver中调用self?.bufferState()

        private func bufferState() {
        if let currentItem = self.avPlayer.currentItem {
            if currentItem.status == AVPlayerItemStatus.readyToPlay {
                if currentItem.isPlaybackLikelyToKeepUp {
                    print("Playing ")
                } else if currentItem.isPlaybackBufferEmpty {
                    print("Buffer empty - show loader")
                }  else if currentItem.isPlaybackBufferFull {
                    print("Buffer full - hide loader")
                } else {
                    print("Buffering ")
                }
            } else if currentItem.status == AVPlayerItemStatus.failed {
                print("Failed ")
            } else if currentItem.status == AVPlayerItemStatus.unknown {
                print("Unknown ")
            }
        } else {
            print("avPlayer.currentItem is nil")
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-23
      • 1970-01-01
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-16
      • 1970-01-01
      • 2016-04-21
      相关资源
      最近更新 更多