如何减少iOS AVPlayer启动延迟

时间:2012-06-23 17:03:29

标签: ios delay avplayer

请注意,对于以下问题:所有资产都是设备上的本地资产 - 没有网络流媒体正在发生。视频包含音轨。

我正在开发一款iOS应用程序,该应用程序需要以最小延迟播放视频文件才能启动相关视频片段。不幸的是,在我们真正需要启动之前,我们不知道下一个具体的视频剪辑。具体来说:当一个视频片段正在播放时,我们将知道下一组(大约)10个视频片段是什么,但我们不知道究竟是哪一个,直到及时“#”;播放下一个片段。

我在查看实际启动延迟时所做的是在视频播放器上调用addBoundaryTimeObserverForTimes,时间段为1毫秒,以查看视频实际开始播放的时间,并且该时间戳与代码中第一个位置的差异,表示开始播放哪个资产。

从我迄今为止所看到的情况来看,我发现使用AVAsset加载的组合,然后在准备就绪之后创建AVPlayerItem,然后在我打电话之前等待AVPlayerStatusReadyToPlay,往往需要1到3秒才能开始剪辑。

我已切换到我认为大致相同的内容:调用[AVPlayerItem playerItemWithURL:]并等待AVPlayerItemStatusReadyToPlay播放。大致相同的表现。

我观察的一件事是第一个AVPlayer项目加载比其余项目慢。似乎有一个想法是在尝试播放第一个视频之前用短/空资产预先飞行AVPlayer可能是一个很好的通用做法。 [Slow start for AVAudioPlayer the first time a sound is played

我希望尽可能地缩短视频开始时间,并且有一些可以尝试的事情的想法,但是希望得到任何可能提供帮助的人的指导。

更新:想法7,如下所示,实施后产生约500毫秒的切换时间。这是一种改进,但要更快地实现这一目标会很好。

创意1:使用N AVPlayers(赢了工作)

使用~10 AVPPlayer个对象并启动并暂停所有~10个剪辑,一旦我们知道我们真正需要哪个剪辑,请切换到并取消暂停正确的AVPlayer,然后启动在下一个周期中重复一遍。

我认为这不起作用,因为我已经读过iOS中大约有4个有效AVPlayer's的限制。这里有人在StackOverflow上询问这个问题,并发现了4个AVPlayer限制:fast-switching-between-videos-using-avfoundation

创意2:使用AVQueuePlayer(不会工作)

我不相信将AVPlayerItems推入AVQueuePlayer将会预先加载它们以便无缝启动。 AVQueuePlayer是一个队列,我认为这只会让队列中的下一个视频准备好立即播放。我不知道我们想要播放的约10个视频中的哪一个,直到它开始那个视频。 ios-avplayer-video-preloading

创意3:在后台加载,播放和保留AVPlayerItems(尚未100%确定 - 但看起来不太好)

我正在查看在后台加载和播放每个视频片段的第一秒是否有任何好处(抑制视频和音频输出),并保留对每个AVPlayerItem的引用,以及当我们知道哪个项目需要真实播放时,交换那个项目,然后将后台AVPlayer与活动项目交换。冲洗并重复。

理论是最近播放的AVPlayer/AVPlayerItem可能仍然保留一些准备好的资源,这将使后续播放更快。到目前为止,我还没有看到这方面的好处,但我可能没有为背景正确设置AVPlayerLayer。我怀疑这会从我所见过的事情中真正改善。

创意4:使用不同的文件格式 - 也许加载速度更快?

我目前正在使用.m4v(视频-MPEG4)H.264格式。 H.264有很多不同的编解码器选项,因此有些选项可能比其他选项更快。我发现使用更高级的设置可以缩小文件大小会增加搜索时间,但是没有找到任何相反的选项。

创意5:无损视频格式+ AVQueuePlayer的组合

如果有一种快速加载的视频格式,但也许文件大小是疯狂的,那么一个想法可能是预先准备每个视频片段的前10秒,其版本臃肿但加载速度更快但是用H.264编码的资产来支持这一点。使用AVQueuePlayer,以未压缩文件格式添加前10秒,然后使用H.264中的一个,最多可达10秒的准备/预加载时间。所以我得到了最好的'两个世界:快速启动时间,但也从更紧凑的格式中受益。

创意6:使用非标准AVPlayer /自己编写/使用其他人

考虑到我的需求,也许我不能使用AVPlayer,但必须求助于AVAssetReader,并在前几秒解码(可能将原始文件写入磁盘),当涉及到播放时,请使用原始格式快速播放。对我来说似乎是一个巨大的项目,如果我以天真的方式去做,它不清楚/不太可能更好地工作。每个解码和未压缩的视频帧为2.25 MB。天真地说 - 如果我们以大约30 fps的速度播放视频,我最终会得到~60 MB / s的磁盘读取要求,这可能是不可能的/推动它。显然,我们必须进行一定程度的图像压缩(也许是通过PVRTC进行原生的OpenGL / es压缩格式)......但这有点疯狂。也许有一个我可以使用的图书馆?

创意7:将所有内容合并为一个电影资源,并搜索到时间

可能比上面的一些更容易的一个想法是将所有内容组合成一个电影,并使用seekToTime。问题是我们会四处跳跃。基本上随机访问电影。我认为这可能实际上没问题:avplayer-movie-playing-lag-in-ios5

您认为哪种方法最好?到目前为止,我在缩短延迟方面没有取得太大进展。

6 个答案:

答案 0 :(得分:1)

创建资产后,资产可能没有准备就绪,它可能会像电影的持续时间一样进行计算,请确保包含文件中电影的所有元数据。

答案 1 :(得分:1)

你应该首先尝试选项#7,看看你能不能正常工作。我怀疑它实际上不能满足您的需求,因为搜索时间可能不会足够快,无法在剪辑之间进行无缝切换。如果您尝试了它并且它失败了,那么我会建议您选择4/6选项并查看我专门为此目的设计的iOS库,只需在AVAnimator上进行快速谷歌搜索以了解更多信息。我的库可以实现无缝循环并从一个剪辑切换到另一个剪辑,它非常快,因为视频必须事先解码成文件。在您的情况下,所有10个视频剪辑将在开始之前被解码为文件,但之后在它们之间切换会很快。

答案 2 :(得分:0)

过去没有做过这样的事情,基于你的想法和经验,我会尝试7和1的组合:在10个跟进视频的前几秒预加载一个AVPlayer。然后,由于数据较少,跳过很可能更快,更可靠。当您正在播放所选的片段时,您有足够的时间为后续视频中的其余视频准备AVPlayer。开始结束后,切换到准备好的AVPlayer。总而言之,您在任何给定时间最多都会加载2个AVPlayers。

当然我不知道切换是否可以顺利完成,以免影响播放。

(如果可以,可以将此作为评论添加。)

最好,彼得

答案 3 :(得分:0)

如果我理解你的问题,似乎你有一个连续的视频,你需要立即加载音轨。

如果是这种情况,我建议调查BASS。 BASS是一个非常类似AVPlayer的音频库,可让您(相对)轻松访问iOS中AudioUnits框架的低级API。对你来说意味着什么?这意味着只需要一点点缓冲操作(你甚至可能不需要它,取决于你想要的延迟程度),你可以立即开始播放音乐。

然而,限制扩展到视频,正如我所说,它是一个音频库,因此任何视频操作仍然必须使用AVPlayer完成。但是,只要您使用所有必要选项进行预注册,使用-seekToTime:toleranfeBefore:toleranceAfter:就可以在视频中实现快速搜索。

如果您正在同步多个设备(您的应用程序可能会建议),请发表评论,我很乐意编辑我的答案。

PS:BASS起初可能看起来令人生畏,因为它是类似C的格式,但它真的很容易使用它。

答案 4 :(得分:0)

对于iOS 10.x及更高版本,为了减少AVPlayer启动延迟,我设置了: avplayer.automaticallyWaitsToMinimizeStalling = false;  这似乎为我解决了。这可能会带来其他后果,但我还没有实现这些目标。

我有以下想法: https://stackoverflow.com/a/50598525/9620547

答案 5 :(得分:-2)

以下是AVAsset类提供的一些可能有用的属性和方法:

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;