简体   繁体   English

AVPlayerItem replaceCurrentItemWithPlayerItem阻塞

[英]AVPlayerItem replaceCurrentItemWithPlayerItem Blocking

First a little context about the application... 首先是关于应用程序的一些背景...
- There's a lot of heavy UI operation's involving video players (mostly scrolling) - 有很多涉及视频播放器的大量UI操作(主要是滚动)
- The videos are dynamic and change based on our current page . - 视频是动态的,并根据我们当前的页面进行更改。
- so the video's have to be dynamic and keep changing and also the UI needs to be responsive - 因此视频必须是动态的并且不断变化,并且UI需要响应

I was initially using a MPMoviePlayerController but then due to certain requirements i had to fall back on the AVPlayer 我最初使用的是MPMoviePlayerController但由于某些要求,我不得不回到AVPlayer上
I made my own wrapper for the AVPlayer . 我为AVPlayer制作了自己的包装器。
To change the content in the videoPlayer this is what the method looks like in the AVPlayer-wrapper Class 要更改videoPlayer中的内容,这是AVPlayer-wrapper类中的方法

/**We need to change the whole playerItem each time we wish to change a video url */
-(void)initializePlayerWithUrl:(NSURL *)url
{
    AVPlayerItem *tempItem = [AVPlayerItem playerItemWithURL:url];

    [tempItem addObserver:self forKeyPath:@"status"
                  options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                  context:nil];
    [tempItem addObserver:self forKeyPath:@"playbackBufferEmpty"
                  options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                  context:nil];

    //Not sure if this should be stopped or paused under the ideal circumstances
    //These will be changed to custom enums later
    [self setPlaybackState:MPMoviePlaybackStateStopped];
    [self setLoadState:MPMovieLoadStateUnknown];
    [self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem];

    //This is required only if we wish to pause the video immediately as we change the url
    //[self.videoPlayer pause];
}

Now ofcourse everything was working fine ......except .. 现在一切都很好......除了......

[self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem];

Seems to be blocking the UI for a fraction of a second and during scrolling these is making the UI really unresponsive and ugly also this operation cannot be performed in the background 似乎在几分之一秒内阻止了UI,在滚动期间,这些使得UI真的没有响应和丑陋,这个操作也无法在后台执行

Is there any fix or workaround for this .. ? 有没有任何修复或解决方法...?

The solution I found was to ensure that the underlying AVAsset is ready to return basic info, such as its duration, before feeding it to the AVPlayer . 我找到的解决方案是确保底层AVAsset准备好在将其提供给AVPlayer之前返回基本信息,例如其持续时间。 AVAsset has a method loadValuesAsynchronouslyForKeys: which is handy for this: AVAsset有一个方法loadValuesAsynchronouslyForKeys:这对此非常方便:

AVAsset *asset = [AVAsset assetWithURL:self.mediaURL];
[asset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{
    AVPlayerItem *newItem = [[AVPlayerItem alloc] initWithAsset:asset];
    [self.avPlayer replaceCurrentItemWithPlayerItem:newItem];
}];

In my case the URL is a network resource, and replaceCurrentItemWithPlayerItem: will actually block for several seconds waiting for this information to download otherwise. 在我的情况下,URL是一个网络资源,并且replaceCurrentItemWithPlayerItem:实际上会阻塞几秒钟,否则等待此信息下载。

We had the same problem when building Ultravisual. 构建Ultravisual时遇到了同样的问题。 I can't exactly remember how we solved it, but IIRC it involved doing as much of the item setup as possible on a background thread, and waiting until the new item reports that it is 'ready to play' before calling replaceCurrentItemWithPlayerItem . 我不能完全记住我们是如何解决它的,但IIRC它涉及在后台线程上尽可能多地完成项目设置,并等到新项目报告它在调用replaceCurrentItemWithPlayerItem之前“准备好播放”。

Sadly this involves a voodoo dance with somewhat inconsistent asynchronous KVO, which is no fun. 可悲的是,这涉及一个巫术舞蹈,有点不一致的异步KVO,这没什么好玩的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM