如何减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;