Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么AVPlayer的初始加载速度如此之慢?_Ios_Objective C_Avfoundation_Avplayer - Fatal编程技术网

Ios 为什么AVPlayer的初始加载速度如此之慢?

Ios 为什么AVPlayer的初始加载速度如此之慢?,ios,objective-c,avfoundation,avplayer,Ios,Objective C,Avfoundation,Avplayer,我在iOS中开发了一个应用程序,可以播放视频列表。数据结构是在创建viewController的视图后,我向自己的服务器发送请求,并立即获取所有视频的URL 之后,我开始一个接一个地播放我的URL的第一项。 问题是,对于第一个视频,实际加载需要超过10秒;但是对于那些有时比第一个视频更长、更大的视频,加载所需的时间要少得多(可能是1或2秒) 通常我的第一个视频很短,很小(平均200 KB),但加载时间仍然比我的第二个视频长1 mb(长5倍,小5倍)要长得多 在过去的三天里,我一直在研究这个问题,

我在iOS中开发了一个应用程序,可以播放视频列表。数据结构是在创建viewController的视图后,我向自己的服务器发送请求,并立即获取所有视频的URL

之后,我开始一个接一个地播放我的URL的第一项。 问题是,对于第一个视频,实际加载需要超过10秒;但是对于那些有时比第一个视频更长、更大的视频,加载所需的时间要少得多(可能是1或2秒)

通常我的第一个视频很短,很小(平均200 KB),但加载时间仍然比我的第二个视频长1 mb(长5倍,小5倍)要长得多

在过去的三天里,我一直在研究这个问题,我尝试了很多不同的方法,我将在下面提到,但我的问题是“为什么会发生这种情况?”这不是一个可能解决问题的方法。我想知道为什么会这样,这样我就可以用我对AVFoundation的了解来解决它,或者编写我自己的播放器,最终为我解决这个问题

这是我初始化它的代码:

self.player = [AVPlayer new];
self.playerView = [[NZPlayerView alloc] initWithPlayer:self.player];
self.playerView.videoGravity = AVLayerVideoGravityResizeAspect;
self.playerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.playerView];
// Constraints
请注意,您上面看到的
NZPlayerView
是我的,它只是一个视图,其中包含一个AVPlayerLayer,并为我处理一些额外的事情,如应用程序进入后台和返回,等等。 我不认为这个视图会引起任何问题,因为这个问题对于其他使用其他方法初始化播放器的开发人员来说似乎是持久的

在创建视图并向自己的服务器发送请求后,我会得到一个URL列表,然后使用下面的代码逐个播放

AVPlayerItem *newCurrentItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[self.selectedMovementModel videoURL] url]]];
[self.player replaceCurrentItemWithPlayerItem:newCurrentItem];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
然后,我使用方法
[self.player playentialyatrate:1]播放视频播放器
这是我实际尝试最小化初始暂停的方法之一,我使用方法
[self.player play]播放我的视频播放器

播放完此视频后,我决定是否循环播放该视频,如果不循环,它将返回到同一功能并播放下一个
selectedMovementModel

我还观察了
self.player.status
self.player.rate
self.player.timeControlStatus
self.player.reasonForWaitingToPlay
使用
RACObserve
,其工作方式与
KVO
相同,只是我不必在关闭viewController后清除它,因此也不会出现任何问题

我尝试的方法是:在创建新的
currentItem
后,在其资产上使用:
loadValuesAsynchronouslyForKeys:completionHandler:
。我为新的
currentItem
preferredForwardBufferDuration
设置为一个非常小的数字

我还尝试将我的播放机的
automaticallyWaitsToMinimizeStalling
属性设置为false,但均无效。 我还使用xCode工具分析了我的网络,我的第一个视频和其他视频似乎没有什么不同。iOS开始分块下载视频,然后在这些块可用时立即播放。即使我将播放器配置为在开始之前下载整个视频,我的第一个视频应该比第二个视频早很多,因为它要小得多。 我的一个猜测是,这可能需要更长的时间,因为播放器第一次与我的主机建立连接,然后播放器会在未知的时间内保持该会话。如果来自两个不同网站的两个视频的加载时间相对相似,这是有道理的,但事实并非如此。第一个仍然需要更长的时间

我宁愿不惜一切代价避免的另一个解决方案是,在服务器响应之前,甚至在页面之前,我会创建一个播放器实例,并用一个非常小的短视频加载它,这样它就可以在用户看到长时间加载之前完成它必须做的事情

但在采取如此绝望的措施之前,我更想知道问题的根源

编辑1**:我在应用程序中创建了一个单例,其中包含我在所有视图控制器中使用的视频播放器实例。我用一个URL初始化并加载了它。但是对于列表中的第一个视频,我的视图控制器仍然存在相同的问题。我还认为,也许我的视频播放器没有加载缺少界面,但结果没有变化。 我将尝试阅读Telegram的代码,因为我知道他们正在使用AVPlayer,即使在大多数情况下,他们在播放视频之前下载了视频,但可能有一些关于他们如何初始化视频播放器的线索


提前谢谢大家。

我要回答我自己的问题

AVPlayer最初延迟的原因是一个非常罕见的案例,可能不会发生在任何人身上,但考虑到自己找到答案可能会很有趣,也会让人感到奇怪的满足,我将发布它

经过进一步的调查,我意识到在我的xCode调试器中有日志说,我的视频URL的某个任务正在被“取消”,错误代码为“-999”。这当然很有趣,因为我还没有告诉我的视频播放器开始播放

我还意识到,大约在调用viewController的
viewDidLoad
方法时,我的应用程序使用了超过180 MB的内存

考虑到我没有任何访问权,无法访问正在取消的任务(我自己的请求没有被取消)。我决定关闭
NSURLSessionDataTask
类的cancel方法,我发现了我的问题。在初始化我的模型列表时,我向每个模型添加了一个函数,用于确定我的视频是否应该使用以下代码循环

    _defineWeakSelf;
    AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:[self.videoURL url]]];
    [asset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{
        AVKeyValueStatus status = [asset statusOfValueForKey:@"duration" error:nil];

        weakSelf._shouldLoop = YES;
        if (status == AVKeyValueStatusLoaded)
        {
            CGFloat fullDurationSeconds = CMTimeGetSeconds([asset duration]);
            if (weakSelf._movementType == MovementTypeTime)
                weakSelf._shouldLoop = (fullDurationSeconds < weakSelf.duration);
            else
                weakSelf._shouldLoop = YES;
        }
    }];
\u定义自己;
AVAsset*asset=[AVAsset assetwithur:[NSURL URLWithString:[self.videoURL]];
[asset LoadValuesSynchronouslyForkeys:@[@“duration”]完成处理程序:^{