如何减lessiOS AVPlayer启动延迟

请注意,对于以下问题:设备上的所有资产都是本地的 – 不会发生networkingstream式传输。 video包含音轨。

我正在开发一个iOS应用程序,要求播放video文件的延迟时间最短,以启动video片段。 不幸的是,我们不知道下一个具体的video剪辑,直到我们真的需要启动它。 具体来说:当一个video剪辑正在播放时,我们将知道下一个(大致)10个video剪辑是什么,但是我们不知道到底是哪一个,直到“立即”播放下一个剪辑。

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

从我目前看到的情况来看,我发现使用AVAsset加载组合,然后创build一个AVPlayerItem ,然后在我调用play之前等待AVPlayerStatusReadyToPlay ,往往需要1到3秒开始剪辑。

我已经切换到我认为是大致相同的:调用[AVPlayerItem playerItemWithURL:]并等待AVPlayerItemStatusReadyToPlay播放。 大致相同的performance。

我注意到的一件事情是,第一个AVPlayer项目负载比其他的慢。 似乎有一个想法是在试图播放第一个video之前,用一个短暂的/空的资源预先播放AVPlayer,这可能是一个很好的普遍做法。 [ 第一次播放声音时,AVAudioPlayer启动缓慢

我很乐意尽可能地减lessvideo的开始时间,并且有一些想要尝试的事情,但是希望有人能够提供帮助。

更新:下面的想法7,实现了大约500毫秒的开关时间。 这是一个改进,但它更好地得到这个更快。

想法1:使用N AVPlayers(将不起作用)

使用〜10 AVPPlayer对象,并开始和暂停所有〜10剪辑,一旦我们知道我们真的需要哪一个,切换到,并取消暂停正确的AVPlayer ,并重新开始下一个周期。

我不认为这是有效的,因为我已经读过,在iOS中大约有4个主动AVPlayer's限制。 有人在StackOverflow上询问了这个问题,并发现了AVPlayer的限制: 快速切换video-using-avfoundation

想法2:使用AVQueuePlayer(不起作用)

我不相信把10个AVPlayerItems放到一个AVQueuePlayer可以预先加载它们以便无缝启动。 AVQueuePlayer是一个队列,我认为这只能使队列中的下一个video准备好立即播放。 我不知道我们想要播放的10个video中的哪一个,直到开始播放。 IOS-avplayervideo预载

想法3:在后台加载,播放和保留AVPlayerItems (不是100%肯定 – 但看起来不太好)

我正在看是否有任何好处,加载和播放每个video剪辑的第一秒在背景(抑制video和audio输出),并保持每个AVPlayerItem的引用,当我们知道哪个项目需要播放真实的,交换一个,并交换背景AVPlayer与活动的一个。 冲洗并重复。

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

想法4:使用不同的文件格式 – 也许加载速度更快?

我目前正在使用.m4v(video – MPEG4)H.264格式。 H.264有很多不同的编解码器选项,所以有些选项可能比其他选项更快。 我发现使用更高级的设置可以缩小文件的大小,增加查找时间,但还没有find任何其他方法。

想法5:无损video格式+ AVQueuePlayer的组合

如果存在快速加载的video格式,但是可能文件大小是疯狂的,则可能有一个想法是预先准备每个video剪辑的前10秒,其版本臃肿但加载速度更快,但是返回用H.264编码的资产。 使用AVQueuePlayer,并以未压缩的文件格式添加前10秒,然后使用一个在H.264中准备好预载时间达10秒的内容。 所以我会得到两全其美的“最好的”:快速的开始时间,但也从更紧凑的格式中受益。

想法6:使用非标准的AVPlayer /写我自己的/使用他人的

鉴于我的需要,也许我不能使用AVPlayer,但不得不求助于AVAssetReader,并解码前几秒(可能写入原始文件到磁盘),当涉及到播放,利用原始格式播放回来快。 对我来说,这似乎是一个巨大的项目,如果我以一种天真的方式去解决这个问题,目前还不清楚/甚至不可能更好地工作。 每个解码和未压缩的video帧是2.25 MB。 天真地说 – 如果我们以30fps的速度去播放video,我最终会得到〜60MB / s的磁盘读取需求,这可能是不可能的。 很明显,我们必须做一些图像压缩(也许本机通过PVRTC的OpenGL / es压缩格式)…但是这是疯了。 也许有一个图书馆,我可以使用?

想法7:将所有内容组合成单个电影资源,并seekToTime

一个想法可能比上面的一些更容易,就是把所有的东西组合成一个单一的电影,并使用seekToTime。 事情是,我们会跳到所有的地方。 基本上随机访问电影。 我认为这可能实际上没问题: avplayer-movie-playing-lag-in-ios5

你认为哪种方法最好? 到目前为止,在减less滞后方面,我还没有取得太多的进展。

一旦你创build了资源,它可能没有准备好,它可能会计算像电影的持续时间,一定要在文件中包含电影的所有元数据。

你应该首先尝试#7选项,看看你是否能得到这个工作。 我怀疑它不会真正适合您的需求,因为寻道时间可能不够快,无法在剪辑之间进行无缝切换。 如果你尝试这样做,那么我会build议你做4/6选项,并看看我为此专门devise的iOS库,只需在AVAnimator上进行快速的谷歌search,了解更多信息。 我的库使得实现无缝循环和从一个片段切换到另一个片段成为可能,这是非常快的,因为video必须事先解码成文件。 在你的情况下,所有10个video剪辑将开始之前解码成文件,但之间切换将是快速的。

在过去没有做过这样的事情的情况下,根据您的想法和经验,我会尝试7和1的组合:在10个后续video的前几秒预先加载一个AVPlayer。 那么由于数据较less,跳过很可能会更快,更可靠。 当您正在播放所选片段时,您有足够的时间为后续所选后续video的其余部分准备AVPlayer。 当开始完成时,您切换到准备好的AVPlayer。 所以总的来说,你在任何时候最多可以加载2个AVPlayers。

当然,我不知道切换是否可以顺利完成,不会干扰播放。

(如果可以的话,会添加这个评论)

最好的,彼得

如果我正确地理解了你的问题,似乎你有一个连续的video,你需要加载音轨的片刻通知。

如果是这样的话,我build议看看BASS 。 BASS是一个非常类似于AVPlayer的audio库,可以让您(相对)轻松地访问iOS中AudioUnits框架的低级API。 你的意思是什么? 这意味着通过一点缓冲区操作(你甚至可能不需要它,取决于你想要延迟多less),你可以立即开始播放音乐。

但是,这个限制扩展到video,正如我所说,这是一个audio库,所以任何video操作仍然必须用AVPlayer来完成。 然而,使用-seekToTime:toleranfeBefore:toleranceAfter:只要您使用所有必要的选项进行预注册,就应该能够在video中实现快速search。

如果你在多个设备(你的应用程序可能build议)同步,只是留下评论,我很乐意编辑我的答案。

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

以下是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;