AVPlayer AVPlayerWaitingWhileEvaluatingBufferingRateReason 较大视频加载缓慢

AVPlayer AVPlayerWaitingWhileEvaluatingBufferingRateReason slow loading for larger videos

我有一个正在播放中等大小视频 (~150mb) 的 AVPlayer。最初加载视频时,我发现播放器在 AVPlayerWaitingWhileEvaluatingBufferingRateReason 状态下保持空闲状态超过 10-15 秒。我的问题很简单:如何防止 AVPlayer 长时间“评估缓冲率原因”而不是立即播放视频?

我正在使用自定义资源加载器(尽管在不使用自定义资源加载器的情况下也会出现同样的行为)。这是创建 AVPlayer 的相关代码(所有标准样板):

AVURLAsset * const playerAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
[[playerAsset resourceLoader] setDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];

AVPlayerItem * const playerItem = [[AVPlayerItem alloc] initWithAsset:playerAsset];

AVPlayer * const player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[player play];
_player = player;

然后我有一个处理数据请求的方法,我可以用它来获取有关 AVPlayer 尝试加载的内容的更多信息:

-(void)handleDataRequest:(AVAssetResourceLoadingDataRequest *)dataRequest loadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {

    NSLog(@"handleDataRequest: %lld-%lld (%@)",[dataRequest requestedOffset],[dataRequest requestedOffset] + [dataRequest requestedLength],[[self player] reasonForWaitingToPlay]);

    NSMutableURLRequest * const request = ... // construct the request
    [request setValue:[NSString stringWithFormat:@"bytes=%lld-%lld",[dataRequest requestedOffset],[dataRequest requestedOffset] + [dataRequest requestedLength]] forHTTPHeaderField:@"Range"];

    NSURLSession * const downloadURLSession = ... // get the session
    NSURLSessionDataTask * const dataTask = [downloadURLSession dataTaskWithRequest:request];
    [dataTask resume];

}

现在,进入正题。假设视频长度是~100mb,这是handleDataRequest登录上述方法的结果:

handleDataRequest: 0-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 3080192-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 5570560-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 7143424-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 9699328-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 12713984-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 14811136-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 17235968-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 20054016-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 22675456-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 25427968-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 28311552-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 30932992-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 32374784-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 35192832-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 37224448-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 39780352-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 41549824-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 43778048-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 46465024-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 49414144-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 52166656-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 54984704-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 57802752-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 60293120-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 62783488-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 65732608-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 68550656-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 70975488-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 73531392-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 76480512-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 79495168-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 82313216-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 83951616-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 86573056-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 88866816-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 91422720-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 92667904-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 95289344-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 98172928-100000000 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 32768-5570560 (AVPlayerWaitingWhileEvaluatingBufferingRateReason)
handleDataRequest: 2032769-5570560 (AVPlayerWaitingToMinimizeStallsReason)
handleDataRequest: 4032770-5570560 (AVPlayerWaitingToMinimizeStallsReason)
handleDataRequest: 5668864-22675456 ((null))
handleDataRequest: 7668865-22675456 ((null))
handleDataRequest: 9668866-22675456 ((null))
handleDataRequest: 11668867-22675456 ((null))
handleDataRequest: 13668868-22675456 ((null))

如您所见,有将近 40 个 HTTP 请求只是为了评估缓冲状态原因。这需要很长时间。

这是我试过的方法:

  1. 使用 AVPlayer 的 playImmediatelyAtRate: 而不是 play

我在网上看到这个建议。我想逻辑是立即播放会做到这一点,立即播放。这不起作用,因为播放器仍然需要时间(和请求)在播放前评估缓冲率原因。

  1. 设置AVPlayer的automaticallyWaitsToMinimizeStallingNO

似乎有道理。我们可以告诉玩家不要等待以尽量减少拖延。不幸的是,这失败了,因为播放器在播放之前仍然会发出相同的请求来评估缓冲率(然而,奇怪的是,reasonForWaitingToPlaynull,而这正在发生)。

  1. 调用加载请求的finishLoading方法立即加速缓冲率评估

这里的逻辑是,我可以立即发出加载已完成的信号,而不是在 AVPlayer 评估缓冲率时触发实际的 HTTP 请求。结果各不相同。在一些测试中,视频会立即播放但只播放了几秒钟,而在其他测试中,视频根本无法播放并且会超时。

总之,在播放较大的视频时,有什么办法可以避免这种延迟吗? AVPlayer 是否真的有必要在开始播放视频之前评估缓冲率?

Apple 已确认问题不在于视频的大小,而是格式错误的 MP4 包含太多 moof+mdat 原子。

在这个时间点,这已被确定为按预期工作。虽然,我希望在未来看到一些避免这种初始缓冲的方法,即使 MP4 格式不正确。